简体   繁体   中英

In a singly linked list how do you shift to the right?

I have a class linkedList, which contains the head, tail, and size variables. In this class, I have a shift method, which shifts to the right if the number in the method parameter(shiftAmount) is positive, and to the left, if negative. I understand how to shift to the left but am confused about how to shift right without a prev pointer.

public void shift(int shiftAmount) {
    if(head == null || head.next == null) {
        return;
    }
    if(shiftAmount < 0) {
        shiftAmount = shiftAmount * -1;
        for(int i = 0; i < shiftAmount; i++) {
            Node temp;
            temp = head;
            head = head.next;
            temp.next = null;
            tail.next = temp;
            tail = temp;
        }
    }
    else {
        // how do I shift to the right????????
    }
}

If by "shift" you mean "rotate", such that the values at the ends roll over to the beginning, then it's easy enough.

Eg say we have the list [1, 3, 5, 7, 9, 11] . Here are some examples of "shifts":

shift(0):  [1, 3, 5, 7, 9, 11]
shift(1):  [11, 1, 3, 5, 7, 9]
shift(3):  [7, 9, 11, 1, 3, 5]
shift(5):  [3, 5, 7, 9, 11, 1]
shift(6):  [1, 3, 5, 7, 9, 11]
shift(-1): [3, 5, 7, 9, 11, 1]

As you can see, for a size of 6, shifting 6 right is the same as shifting 0, and shifting 5 right is the same as shifting 1 left.

You can normalize the shift value by calculating modulus size, ie shift % size . Eg for size 6, that will result in a shift value in the range -5 to +5. You can eliminate the left shifts by adding the size and calculating modulus again, ie (shift + size) % size . Combined that means:

int normalizedShift = (shift % size + size) % size;

If the normalized shift is 0, stop. You're done.

Otherwise we need to grab the last normalizedShift nodes and move them up front.

If you draw it, a shift(2) looks like this:

         BEFORE
head                tail
↓                   ↓
1 → 3 → 5 → 7 → 9 → 11

         AFTER
               tail   head
               ↓      ↓
┌→ 1 → 3 → 5 → 7      9 → 11 ─┐
└─────────────────────────────┘

Which is done as follow:

tail.next = head;
//    head                tail
//    ↓                   ↓
// ┌→ 1 → 3 → 5 → 7 → 9 → 11 ─┐
// └──────────────────────────┘

for (int i = 0; i < size - normalizedShift - 1)
    head = head.next;
//                head    tail
//                ↓       ↓
// ┌→ 1 → 3 → 5 → 7 → 9 → 11 ─┐
// └──────────────────────────┘

tail = head;
head = head.next;
//                tail  head
//                ↓     ↓
// ┌→ 1 → 3 → 5 → 7  →  9 → 11 ─┐
// └────────────────────────────┘

tail.next = null;
//                tail  head
//                ↓     ↓
// ┌→ 1 → 3 → 5 → 7     9 → 11 ─┐
// └────────────────────────────┘

All-in-all:

public void shift(int shiftAmount) {
    int normalizedShift = (shiftAmount % size + size) % size;
    if (normalizedShift != 0) {
        tail.next = head;
        for (int i = 0; i < size - normalizedShift - 1; i++)
            head = head.next;
        tail = head;
        head = head.next;
        tail.next = null;
    }
}

Since it is a single linked list you can not shift to the right.
Just replace shiftAmount shift to the right by size - shiftAmount shift to the left.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM