题源:2009年408题源 要求:使用一趟扫描完成
思路一:快慢指针(高效) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class Solution {public : ListNode* removeNthFromEnd (ListNode* head, int n) { ListNode* fast = head; ListNode* slow = head; for (int i = 0 ; i < n; i ++) fast = fast -> next; while (fast && fast -> next) { slow = slow -> next; fast = fast -> next; } if (fast) { slow -> next = slow -> next -> next; return head; } else { return head -> next; } } };
题源:2010年408题源 要求:使用原地算法(即空间复杂度为O(1))解决此题 注意:C语言的 memcpy
函数不可处理源内存片和目标内存片有重合的情况,否则属于未定义行为。而其升级版 memmove
函数已经不再是原地算法。
思路一:使用类似于冒泡排序的思想,每次操作只转动一次数组,直到转动(k%size)次 时间复杂度:$$O(k\times Size)\approx O(Size^2)$$ 空间复杂度:$$O(1)$$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 void rotate (int * nums, int numsSize, int k) { k %= numsSize; int tail = 0 ; for (int t = 0 ; t < k; t++) { tail = *(nums + numsSize - 1 ); for (int i = numsSize - 1 ; i > 0 ; i--) { *(nums + i) = *(nums + i - 1 ); } *nums = tail; } }
运行结果:超时(但是算法应该正确)
思路二:直接使用C标准库 时间复杂度:$$O(1)$$ 空间复杂度:$$O(Size)$$
1 2 3 4 5 6 7 8 void rotate (int * nums, int numsSize, int k) { k %= numsSize; int * temp = malloc (sizeof (int ) * numsSize); memcpy (temp, nums + (numsSize - k), k * sizeof (int )); memcpy (temp + k, nums, (numsSize - k) * sizeof (int )); memcpy (nums, temp, numsSize * sizeof (int )); free (temp); }
运行通过。
思路三:数组二次翻转 参考题解:https://leetcode.cn/problems/rotate-array/solutions/683855/shu-zu-fan-zhuan-xuan-zhuan-shu-zu-by-de-5937 时间复杂度:$$O(2n)$$ 空间复杂度:$$O(1)$$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void reverse (int *nums, int numsSize) { for (int i = 0 ; i < numsSize / 2 ; i++) { int temp = *(nums + i); *(nums + i) = *(nums + numsSize - i - 1 ); *(nums + numsSize - i - 1 ) = temp; } } void rotate (int * nums, int numsSize, int k) { k %= numsSize; reverse(nums, numsSize); reverse(nums, k); reverse(nums + k, numsSize - k); }