Min Value from Stack - c

I have a stack which contains some integer data. I want to find out the min value from Stack in O(1) time. Any idea?
PS: There is no ordering (increasing/decreasing) of data in Stack.
Thanks,
Naveen

Use two stacks. One is the data, one is the minimums. When you push onto the data stack, push the new minimum onto the minimums stack (the new minimum is the min of the item you're pushing and whatever is currently on the top of the minimums stack), and when you pop, pop off of both stacks (so that the two stacks always have the same number of elements). To find the minimum element, just look at the top of the minimums stack.
Pushing, popping and finding the min value are O(1).

O(n) is the best you're gonna do - you'd have to check each one of the values and compare them to the aggregator minimum, otherwise how would you know you got the lowest?
If you want, you can store the minimum as the values are added, making the pushes more expensive for the benefit of an O(1) read (of the pre-calculated minimum), but that's it.

A stack by definition is push/pop (LIFO) data structure. You can't using a single stack!

I am not sure why you expect to do this in constant time for arbitrary length. The best you will be able to do is O(n)

You'll probably want some kind of priority heap if you want to always pop the least element. If you want to pop what was last pushed, but be able to know the order of the elements remaining in the stack, some kind of search tree e.g. red-black will support deletion of an element from an arbitrary position (your stack would have a pointer to the tree node so when you pop you can find it).
If you only need to know the minimum (or max) remaining in the stack then ESRogs' is optimal.

Here is the Python implementation of ESRogs algorithm using lists as stacks:
class ConstantStack:
def __init__(self):
self.stack = []
self.min_stack = []
def push(self,item):
self.stack.append(item)
if len(self.min_stack) == 0:
self.min_stack.append(item)
return
# Get the smaller item between the pushed item and the top of the stack
smallest = min(item,self.min_stack[-1])
self.min_stack.append(smallest)
def pop(self):
self.min_stack.pop()
return self.stack.pop()
def min(self):
# NOTE: min_stack[-1] is equivalent to peek()
return self.min_stack[-1]
Here is an example of its usage:
>>> s = ConstantStack()
>>> s.push(3)
>>> s.push(7)
>>> s.push(6)
>>> s.push(1)
>>> s.min()
1
>>> s.pop()
1
>>> # Now that 1 is gone, 3 is the next smallest
>>> s.min()
3
>>> s.pop()
6
>>> # 6 was popped but 3 still remains the smallest
>>> s.min()
3
>>> s.pop()
7
>>> s.min()
3
>>> s.pop()
3

#define STACKSIZE 50
typedef struct stack
{
int item[STACKSIZE];
int top;
}MULSTACKEX;
void InitStack(MULSTACKEX &st)
{
st.item[STACKSIZE] = 0;
st.top = -1;
}
void Push(MULSTACKEX &st1, MULSTACKEX &st2, int elem)
{
if(st1.top == -1)
{
st1.top++;
st1.item[st1.top] = elem;
st2.top++;
st2.item[st2.top] = elem;
}
else
{
st1.top++;
st1.item[st1.top] = elem;
if(elem < st2.item[st2.top])
{
st2.top++;
st2.item[st2.top] = elem;
}
}
}
void Display(MULSTACKEX &st1, MULSTACKEX &st2)
{
cout<<"stack1 elements: "<<endl;
for(int i = 0; i <= st1.top; i++)
{
cout<<st1.item[i]<<"->";
}
cout<<endl;
cout<<"stack2 elements: "<<endl;
for(int i = 0; i <= st2.top; i++)
{
cout<<st2.item[i]<<"->";
}
}
int Pop(MULSTACKEX &st1, MULSTACKEX &st2)
{
int elem = 0;
if(st1.item[st1.top] == st2.item[st2.top])
{
elem = st2.item[st2.top];
st2.top--;
elem = st1.item[st1.top];
st1.top--;
}
else
{
elem = st1.item[st1.top];
st1.top--;
}
return elem;
}
int FindMin(MULSTACKEX &st2)
{
int elem = st2.item[st2.top];
return elem;
}
int _tmain(int argc, _TCHAR* argv[])
{
MULSTACKEX stack1, stack2;
InitStack(stack1);
InitStack(stack2);
Push(stack1,stack2,13);
Push(stack1,stack2,17);
Push(stack1,stack2,5);
Display(stack1,stack2);
int min_elem1 = FindMin(stack2);
cout<<"Min element in the list is: "<<min_elem1<<endl<<endl;
int deletedelem2 = Pop(stack1,stack2);
cout<<"Pop element from the stack:"<< deletedelem2 <<endl<<endl;
Display(stack1,stack2);
cout<<endl<<endl;
Push(stack1,stack2,19);
Push(stack1,stack2,8);
Display(stack1,stack2);
cout<<endl<<endl;
int deletedelem1 = Pop(stack1,stack2);
cout<<"Pop element from the stack:"<< deletedelem1 <<endl<<endl;
Display(stack1,stack2);
int min_elem2 = FindMin(stack2);
cout<<"Min element in the list is: "<<min_elem2<<endl<<endl;
return 0;
}

Instead of pushing 1 value, we push a pair of numbers. first element will be element that you want to push, second element would be minimum element of the stack and we should keep track of the minimum element. (element,minOfStack)
let say you have an empty array. when first you push data to the stack,firs element is also minumum value.
data=[(1,1)]
then you add value 2. you check the minimim value of the stack which is 1, 1<2, so you push (2,1) to the array
data=[(1,1),(2,1)]
Here is the python implementation
class StackTrackingMin:
def __init__(self):
self._data=[]
def push(self,x:int)->None:
currentMin=self.getMin()
if currentMin==None or currentMin>x:
currentMin=x
self._data.append((x,currentMin))
def pop(self)->None:
self._data.pop() # pop does not return anything
def top(self)->int:
return self._date[-1] if self._data else None
def getMin(self)->int:
return self._data[-1][1] if self._data else None

Related

Fastest Permutation algorithms for unique permutations using smallest memory [duplicate]

For example, string "AAABBB" will have permutations:
"ABAABB",
"BBAABA",
"ABABAB",
etc
What's a good algorithm for generating the permutations? (And what's its time complexity?)
For a multiset, you can solve recursively by position (JavaScript code):
function f(multiset,counters,result){
if (counters.every(x => x === 0)){
console.log(result);
return;
}
for (var i=0; i<counters.length; i++){
if (counters[i] > 0){
_counters = counters.slice();
_counters[i]--;
f(multiset,_counters,result + multiset[i]);
}
}
}
f(['A','B'],[3,3],'');
This is not full answer, just an idea.
If your strings has fixed number of only two letters I'll go with binary tree and good recursion function.
Each node is object that contains name with prefix of parent name and suffix A or B furthermore it have numbers of A and B letters in the name.
Node constructor gets name of parent and number of A and B from parent so it needs only to add 1 to number of A or B and one letter to name.
It doesn't construct next node if there is more than three A (in case of A node) or B respectively, or their sum is equal to the length of starting string.
Now you can collect leafs of 2 trees (their names) and have all permutations that you need.
Scala or some functional language (with object-like features) would be perfect for implementing this algorithm. Hope this helps or just sparks some ideas.
Since you actually want to generate the permutations instead of just counting them, the best complexity you can hope for is O(size_of_output).
Here's a good solution in java that meets that bound and runs very quickly, while consuming negligible space. It first sorts the letters to find the lexographically smallest permutation, and then generates all permutations in lexographic order.
It's known as the Pandita algorithm: https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order
import java.util.Arrays;
import java.util.function.Consumer;
public class UniquePermutations
{
static void generateUniquePermutations(String s, Consumer<String> consumer)
{
char[] array = s.toCharArray();
Arrays.sort(array);
for (;;)
{
consumer.accept(String.valueOf(array));
int changePos=array.length-2;
while (changePos>=0 && array[changePos]>=array[changePos+1])
--changePos;
if (changePos<0)
break; //all done
int swapPos=changePos+1;
while(swapPos+1 < array.length && array[swapPos+1]>array[changePos])
++swapPos;
char t = array[changePos];
array[changePos] = array[swapPos];
array[swapPos] = t;
for (int i=changePos+1, j = array.length-1; i < j; ++i,--j)
{
t = array[i];
array[i] = array[j];
array[j] = t;
}
}
}
public static void main (String[] args) throws java.lang.Exception
{
StringBuilder line = new StringBuilder();
generateUniquePermutations("banana", s->{
if (line.length() > 0)
{
if (line.length() + s.length() >= 75)
{
System.out.println(line.toString());
line.setLength(0);
}
else
line.append(" ");
}
line.append(s);
});
System.out.println(line);
}
}
Here is the output:
aaabnn aaanbn aaannb aabann aabnan aabnna aanabn aananb aanban aanbna
aannab aannba abaann abanan abanna abnaan abnana abnnaa anaabn anaanb
anaban anabna ananab ananba anbaan anbana anbnaa annaab annaba annbaa
baaann baanan baanna banaan banana bannaa bnaaan bnaana bnanaa bnnaaa
naaabn naaanb naaban naabna naanab naanba nabaan nabana nabnaa nanaab
nanaba nanbaa nbaaan nbaana nbanaa nbnaaa nnaaab nnaaba nnabaa nnbaaa

Longest path with N steps in matrix

I'm trying to find a simple path of length N in a RxC matrix, given a starting cell. The path should follow a restriction, given by a boolean function. The goal is to later use this to find the longest path in the matrix.
I got a solution set up, however I don't know how to modify it to know when a solution does not exist.
My solution consists of a DFS approach using backtracking. The solution is correct when there is one, but the program returns the longest path found instead of saying such path doesn't exist.
I know there are similar problems with solutions available but I'd like to understand where my logic is failing.
Here's the code (from a cell we can move in all 8 directions):
Bool DFS(Map *map,Point* srcPt,short steps,Bool (*restrictionCompare)(Point *p1, Point *p2))
{
Point *target;
short row = getPointRow(srcPt);
short col = getPointCol(srcPt);
// Found N-steps path!
if (steps == 0)
{
puts("Path found!\n");
return 1;
}
//Mark the M[row][col] as visited
markAsVisited(map,row,col);
// Iterate over all 8 directions of a cell
for (short i = 0; i < DIRECTIONS; ++i)
{
short coords[2];
// Get a valid adjacent cell
if (getNeighbour(map,srcPt,i,coords,restrictionCompare) == FALSE) continue;
target = getMapPoint(map,coords[0],coords[1]); // This is the valid neighbour
//if cell wasn't visited before...
if (isVisited(target) == FALSE)
{
// ..recursively call DFS from cell
if(DFS(map,target,--steps,restrictionCompare) == TRUE)
{
// Show point
showPoint(target);
return TRUE;
}
}
}
// Backtrack
markAsUnvisited(map,row,col);
return FALSE;
}
An example of path of length found by the program:
Any suggestions on how to improve the code's efficiency is also welcome.

Move Zeroes in Scala

I'm working on "Move Zeroes" of leetcode with scala. https://leetcode.com/problems/move-zeroes/description/
Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements. You must do this in-place without making a copy of the array.
I have a solution which works well in IntelliJ but get the same Array with input while executing in Leetcode, also I'm not sure whether it is done in-place... Something wrong with my code ?
Thanks
def moveZeroes(nums: Array[Int]): Array[Int] = {
val lengthOrig = nums.length
val lengthFilfter = nums.filter(_ != 0).length
var numsWithoutZero = nums.filter(_ != 0)
var numZero = lengthOrig - lengthFilfter
while (numZero > 0){
numsWithoutZero = numsWithoutZero :+ 0
numZero = numZero - 1
}
numsWithoutZero
}
And one more thing: the template code given by leetcode returns Unit type but mine returns Array.
def moveZeroes(nums: Array[Int]): Unit = {
}
While I agree with #ayush, Leetcode is explicitly asking you to use mutable states. You need to update the input array so that it contains the changes. Also, they ask you to do that in a minimal number of operations.
So, while it is not idiomatic Scala code, I suggest you a solution allong these lines:
def moveZeroes(nums: Array[Int]): Unit = {
var i = 0
var lastNonZeroFoundAt = 0
while (i < nums.size) {
if(nums(i) != 0) {
nums(lastNonZeroFoundAt) = nums(i)
lastNonZeroFoundAt += 1
}
i += 1
i = lastNonZeroFoundAt
while(i < nums.size) {
nums(i) = 0
i += 1
}
}
As this is non-idomatic Scala, writing such code is not encouraged and thus, a little bit difficult to read. The C++ version that is shown in the solutions may actually be easier to read and help you to understand my code above:
void moveZeroes(vector<int>& nums) {
int lastNonZeroFoundAt = 0;
// If the current element is not 0, then we need to
// append it just in front of last non 0 element we found.
for (int i = 0; i < nums.size(); i++) {
if (nums[i] != 0) {
nums[lastNonZeroFoundAt++] = nums[i];
}
}
// After we have finished processing new elements,
// all the non-zero elements are already at beginning of array.
// We just need to fill remaining array with 0's.
for (int i = lastNonZeroFoundAt; i < nums.size(); i++) {
nums[i] = 0;
}
}
Your answer gives TLE (Time Limit Exceeded) error in LeetCode..I do not know what the criteria is for that to occur..However i see a lot of things in your code that are not perfect .
Pure functional programming discourages use of any mutable state and rather focuses on using val for everything.
I would try it this way --
def moveZeroes(nums: Array[Int]): Array[Int] = {
val nonZero = nums.filter(_ != 0)
val numZero = nums.length - nonZero.length
val zeros = Array.fill(numZero){0}
nonZero ++ zeros
}
P.S - This also gives TLE in Leetcode but still i guess in terms of being functional its better..Open for reviews though.

Given an array, find combinations of n numbers that are less than c

This is a tough one, at least for my minimal c skills.
Basically, the user enters a list of prices into an array, and then the desired number of items he wants to purchase, and finally a maximum cost not to exceed.
I need to check how many combinations of the desired number of items are less than or equal to the cost given.
If the problem was a fixed number of items in the combination, say 3, it would be much easier with just three loops selecting each price and adding them to test.
Where I get stumped is the requirement that the user enter any number of items, up to the number of items in the array.
This is what I decided on at first, before realizing that the user could specify combinations of any number, not just three. It was created with help from a similar topic on here, but again it only works if the user specifies he wants 3 items per combination. Otherwise it doesn't work.
// test if any combinations of items can be made
for (one = 0; one < (count-2); one++) // count -2 to account for the two other variables
{
for (two = one + 1; two < (count-1); two++) // count -1 to account for the last variable
{
for (three = two + 1; three < count; three++)
{
total = itemCosts[one] + itemCosts[two] + itemCosts[three];
if (total <= funds)
{
// DEBUG printf("\nMatch found! %d + %d + %d, total: %d.", itemCosts[one], itemCosts[two], itemCosts[three], total);
combos++;
}
}
}
}
As far as I can tell there's no easy way to adapt this to be flexible based on the user's desired number of items per combination.
I would really appreciate any help given.
One trick to flattening nested iterations is to use recursion.
Make a function that takes an array of items that you have selected so far, and the number of items you've picked up to this point. The algorithm should go like this:
If you have picked the number of items equal to your target of N, compute the sum and check it against the limit
If you have not picked enough items, add one more item to your list, and make a recursive call.
To ensure that you do not pick the same item twice, pass the smallest index from which the function may pick. The declaration of the function may look like this:
int count_combinations(
int itemCosts[]
, size_t costCount
, int pickedItems[]
, size_t pickedCount
, size_t pickedTargetCount
, size_t minIndex
, int funds
) {
if (pickedCount == pickedTargetCount) {
// This is the base case. It has the code similar to
// the "if" statement from your code, but the number of items
// is not fixed.
int sum = 0;
for (size_t i = 0 ; i != pickedCount ; i++) {
sum += pickedItems[i];
}
// The following line will return 0 or 1,
// depending on the result of the comparison.
return sum <= funds;
} else {
// This is the recursive case. It is similar to one of your "for"
// loops, but instead of setting "one", "two", or "three"
// it sets pickedItems[0], pickedItems[1], etc.
int res = 0;
for (size_t i = minIndex ; i != costCount ; i++) {
pickedItems[pickedCount] = itemCosts[i];
res += count_combinations(
itemCosts
, costCount
, pickedItems
, pickedCount+1
, pickedTargetCount
, i+1
, funds
);
}
return res;
}
}
You call this function like this:
int itemCosts[C] = {...}; // The costs
int pickedItems[N]; // No need to initialize this array
int res = count_combinations(itemCosts, C, pickedItems, 0, N, 0, funds);
Demo.
This can be done by using a backtracking algorithm. This is equivalent to implementing a list of nested for loops. This can be better understood by trying to see the execution pattern of a sequence of nested for loops.
For example lets say you have, as you presented, a sequence of 3 fors and the code execution has reached the third level (the innermost). After this goes through all its iterations you return to the second level for where you go to the next iteration in which you jump again in third level for. Similarly, when the second level finishes all its iteration you jump back to the first level for which continues with the next iteration in which you jump in the second level and from there in the third.
So, in a given level you try go to the deeper one (if there is one) and if there are no more iterations you go back a level (back track).
Using the backtracking you represent the nested for by an array where each element is an index variable: array[0] is the index for for level 0, and so on.
Here is a sample implementation for your problem:
#define NUMBER_OF_OBJECTS 10
#define FORLOOP_DEPTH 4 // This is equivalent with the number of
// of nested fors and in the problem is
// the number of requested objects
#define FORLOOP_ARRAY_INIT -1 // This is a init value for each "forloop" variable
#define true 1
#define false 0
typedef int bool;
int main(void)
{
int object_prices[NUMBER_OF_OBJECTS];
int forLoopsArray[FORLOOP_DEPTH];
bool isLoopVariableValueUsed[NUMBER_OF_OBJECTS];
int forLoopLevel = 0;
for (int i = 0; i < FORLOOP_DEPTH; i++)
{
forLoopsArray[i] = FORLOOP_ARRAY_INIT;
}
for (int i = 0; i < NUMBER_OF_OBJECTS; i++)
{
isLoopVariableValueUsed[i] = false;
}
forLoopLevel = 0; // Start from level zero
while (forLoopLevel >= 0)
{
bool isOkVal = false;
if (forLoopsArray[forLoopLevel] != FORLOOP_ARRAY_INIT)
{
// We'll mark the loopvariable value from the last iterration unused
// since we'll use a new one (in this iterration)
isLoopVariableValueUsed[forLoopsArray[forLoopLevel]] = false;
}
/* All iterations (in all levels) start basically from zero
* Because of that here I check that the loop variable for this level
* is different than the previous ones or try the next value otherwise
*/
while ( isOkVal == false
&& forLoopsArray[forLoopLevel] < (NUMBER_OF_OBJECTS - 1))
{
forLoopsArray[forLoopLevel]++; // Try a new value
if (loopVariableValueUsed[forLoopsArray[forLoopLevel]] == false)
{
objectUsed[forLoopsArray[forLoopLevel]] = true;
isOkVal = true;
}
}
if (isOkVal == true) // Have we found in this level an different item?
{
if (forLoopLevel == FORLOOP_DEPTH - 1) // Is it the innermost?
{
/* Here is the innermost level where you can test
* if the sum of all selected items is smaller than
* the target
*/
}
else // Nope, go a level deeper
{
forLoopLevel++;
}
}
else // We've run out of values in this level, go back
{
forLoopsArray[forLoopLevel] = FORLOOP_ARRAY_INIT;
forLoopLevel--;
}
}
}

Getting list elements from Prolog in a C interface

I try to implement a C interface using a Prolog script based on GNU Prolog. My problem is to get single elements of a nested Prolog list.
Actually my C code looks like
...
int func;
PlTerm arg[10];
PlTerm *sol_gb;
PlBool res;
int nmb;
char *strHead;
char *strTail;
PlLong nummero;
PlTerm pl_nummero;
Pl_Start_Prolog(argc, argv);
Pl_Query_Begin(PL_TRUE);
arg[0] = Pl_Mk_String(strRName);
arg[1] = Pl_Mk_Variable();
arg[2] = Pl_Mk_Variable();
arg[3] = Pl_Mk_String("true");
res = Pl_Query_Call(func, 4, arg);
sol_gb = Pl_Rd_List(arg[2]);
nmb = Pl_List_Length(sol_gb[0]);
strHead = Pl_Write_To_String(sol_gb[0]);
printf("strHead = %s\n",strHead);
strTail = Pl_Write_To_String(sol_gb[1]);
printf("strTail = %s\n",strTail);
...
The Prolog list returned in arg[2] looks like
[ [ Spezial Bolognese,
[2, ,Zwiebeln,300,gramm,Hackfleisch,10, ,Tomaten,
100,ml,Sahne,500,gramm,Spaghetti]
],
[ Spaghetti Bolognese,
[2, ,Zwiebeln gehackt,300,gramm,Hackfleisch,10, ,Fleischtomaten,
100,ml,Sahne,500,gramm,Spaghetti]
]
]
The output of the conversion into a String is
strHead = [Spezial Bolognese,[2, ,Zwiebeln gehackt,300,gramm,Hackfleisch,
10, ,Fleischtomaten,100,ml,Sahne,500,gramm,Spaghetti]]
strTail = [[Spaghetti Bolognese,[2, ,Zwiebeln gehackt,300,gramm,Hackfleisch,
10, ,Fleischtomaten,100,ml,Sahne,500,gramm,Spaghetti]]]
So I assume, I am "nearly there" but as I have to re-activate my C knowledge I do not get the solution how to enter in the next level of the list to get finally each element as string ("Spezial Bolognese", next step: "2", "Zwiebeln" etc.).
How can I step through the Prolog list in C?
I would be very happy about every hint, thank you again!
To get the content of a list from the C-code you can use 2 kind of functions.
First possibility (simple since the list is seen as a flat object but requires more memory and needs a proper list, i.e. does not work for lists not terminated by [])
int Pl_Rd_Proper_List_Check(PlTerm the_prolog_list, PlTerm *the_array_receiving_arguments);
this functions receives an array (it is up to you to ensure it is large enough), stores each element of the list in the array and returns the total number of elements. Example:
PlTerm list = ...some Prolog list...
int nElem = Pl_List_Length(list);
PlTerm *elem = (PlTerm *) calloc(nElem, sizeof(PlTerm));
Pl_Rd_Proper_List_Check(list, elem);
int i;
for(i = 0; i < nElem; i++) {
// here there is an argument in elem[i], let's print it
Pl_Write(elem[i]);
}
Second possibility (more general but see a list as a chained list, each cell contains the head and a tail (a list))
PlTerm *Pl_Rd_List(PlTerm the_prolog_list);
This function returns an array of 2 elements corresponding to the head and the tail of the received list. This function should be called on each element of the list; either you know the number of elements or you test the end of the list (e.g. waiting for the end of list atom []). Here is a code doing this (it is expected to be inside the above loop since we know the second argument of the list is a nested list.
PlTerm list = ... some Prolog list...;
while(!Pl_Un_Atom(Pl_Atom_Nil(), list)) {
PlTerm *lst_arg = Pl_Rd_List(list); // [0] = head element, [1] = tail list
// here there is an argument in lst_arg[0], let's print it
Pl_Write(lst_arg[0]);
list = lst_arg[1];
}
In your example, the first list looks like:
[ 'Spezial Bolognese',
[2,' ','Zwiebeln',
300,'gramm','Hackfleisch',
10,' ','Tomaten',
100,'ml','Sahne',
500,'gramm','Spaghetti']
]
so the second element is a nested list. The following code uses the first method for the above list (which has 2 elements), and the second method for the nested list:
nElem = Pl_List_Length(sol_gb[0]);
PlTerm *elem = (PlTerm *) calloc(nElem, sizeof(PlTerm));
Pl_Rd_Proper_List_Check(sol_gb[0], elem);
int i;
for(i = 0; i < nmb; i++) {
if (i != 1) {
Pl_Write(elem[i]);
printf("\n");
} else { // we know it is a list
printf("(");
PlTerm list = elem[i];
while(!Pl_Un_Atom(Pl_Atom_Nil(), list)) {
PlTerm *lst_arg = Pl_Rd_List(list); // [0] = head element, [1] = tail list
printf(" ");
Pl_Write(lst_arg[0]);
list = lst_arg[1];
}
printf(" )\n");
}
}
Here should be the output
Spezial Bolognese
( 2 Zwiebeln 300 gramm Hackfleisch 10 Tomaten 100 ml Sahne 500 gramm Spaghetti )
The sample code you give of the lists of lists sounds like a textbook example of a very bad choice for knowledge representation. I strongly suggest you change it to a more declarative representation. Something like:
% pizza(Name, Steps)
pizza('Spezial Bolognese', ...).
...
where Steps could be a list of step(...) terms. This would potentially make processing the information easier and more efficient. For example, in the Prolog side, you could then use the standard arg/3 predicate to access a specific element in a step. With lists, you have no choice other than traversing them every time you want an element other than the list head.

Resources