在单链表中,如何向右移动?

huangapple go评论71阅读模式
英文:

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

问题

我有一个名为linkedList的类,其中包含头部(head)、尾部(tail)和大小(size)变量。在这个类中,我有一个shift方法,如果方法参数(shiftAmount)中的数字为正数,它会向右移动,如果为负数,它会向左移动。我知道如何向左移动,但不太清楚如何在没有prev指针的情况下向右移动。

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 {
        // 如何向右移动????????
    }
}
英文:

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 &lt; 0) {
		shiftAmount = shiftAmount * -1;
    	for(int i = 0; i &lt; 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????????
	}
}

答案1

得分: 2

如果你所指的 "shift" 是指 "rotate",即将两端的值滚动到列表的开始,那么就足够简单。

例如,假设我们有列表 [1, 3, 5, 7, 9, 11]。以下是一些 "shift" 的示例:

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]

正如你所看到的,对于大小为 6,将其右移 6 与右移 0 是相同的,将其右移 5 与左移 1 是相同的。

你可以通过计算模数大小来"归一化"移位值,即 shift % size。例如,对于大小 6,这将导致一个在 -5 到 +5 范围内的移位值。你可以通过添加大小并再次计算模数来消除左移,即 (shift + size) % size。综合起来就是:

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

如果归一化的移位值为 0,则停止。完成了。

否则,我们需要获取最后 normalizedShift 个节点并将它们移到前面。

如果你绘制出来,shift(2) 看起来像这样:

         之前
头                  尾
↓                   ↓
1 → 3 → 5 → 7 → 9 → 11

         之后
               尾     头
               ↓      ↓
┌→ 1 → 3 → 5 → 7      9 → 11 ─┐
└─────────────────────────────┘

操作如下:

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

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

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

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

总而言之:

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

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

E.g. 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, i.e. shift % size. E.g. 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, i.e. (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 &lt; 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 &lt; size - normalizedShift - 1; i++)
            head = head.next;
        tail = head;
        head = head.next;
        tail.next = null;
    }
}

答案2

得分: 0

因为它是单链表,所以无法向右移动。只需将 shiftAmount 右移更改为 size - shiftAmount 左移。

英文:

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

huangapple
  • 本文由 发表于 2020年9月16日 08:37:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/63911554.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定