【Leetcode】旋转系列题目总结如下:
旋转系列问题
189. 轮转数组
1.题目描述
leetcode链接:189. 轮转数组
2.思路分析
根据k来轮转数组,要求空间复杂度为O(1),因此需要在原数组上进行反转,因此可以先反转整个数组,再把前k个反转,再把后n-k个反转。
需要注意的是:k大于nums.length的情况,需要用k对nums.length取模。
3.参考代码
class Solution {
public void rotate(int[] nums, int k) {
int n = nums.length;
k = k % n;
reverse(nums, 0, n - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, n - 1);
}
public void reverse(int[] nums, int start, int end) {
while (start < end) {
int tmp = nums[start];
nums[start++] = nums[end];
nums[end--] = tmp;
}
}
}
面试题 01.07. 旋转矩阵
1.题目描述
leetcode链接:面试题 01.07. 旋转矩阵
2.思路分析
每次交换菱形四个顶点。
3.参考代码
class Solution {
public void rotate(int[][] matrix) {
// 交换菱形四个顶点
int n = matrix.length;
int start = 0, end = n - 1;
while (start < end) {
for (int i = 0; i < end - start; i++) {
int tmp = matrix[start][start + i];
matrix[start][start + i] = matrix[end - i][start];
matrix[end - i][start] = matrix[end][end - i];
matrix[end][end - i] = matrix[start + i][end];
matrix[start + i][end] = tmp;
}
start++;
end--;
}
}
}
剑指 Offer 24. 反转链表
1.题目描述
leetcode链接:剑指 Offer 24. 反转链表
2.思路分析
方法一:迭代法(双指针)
方法二:递归
使用递归法遍历链表,当越过尾节点后终止递归,在回溯时修改各节点的 next 引用指向。
3.参考代码
方法一:迭代法(双指针)
class Solution {
public ListNode reverseList(ListNode head) {
ListNode dumpy = null;
while (head != null) {
ListNode tmp = head.next;
head.next = dumpy;
dumpy = head;
head = tmp;
}
return dumpy;
}
}
方法二:递归
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null || head.next==null){
return head;
}
ListNode node = reverseList(head.next);
head.next.next = head;
head.next = null;
return node;
}
}
61. 旋转链表
1.题目描述
leetcode链接:61. 旋转链表
2.思路分析
先统计链表长度,同时将链表首尾相连,然后对k进行取模,判断旋转点。然后旋转点以后的点赋值为新节点,再把旋转点之后的点赋值为null即可。
3.参考代码
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if (head == null || head.next == null || k == 0) return head;
ListNode p = head;
int n = 1; // 统计链表长度
while (p.next != null) {
n++;
p = p.next;
}
k %= n;
if (k == 0) return head;
p.next = head; // 首尾相连
// 找到旋转点
for (int i = 0; i < n - k; i++) {
p = p.next;
}
ListNode newHead = p.next; // 将旋转点后面的点赋值给新的头节点
p.next = null; // 将该旋转点点之后赋为null
return newHead;
}
}
396. 旋转函数
1.题目描述
leetcode链接:396. 旋转函数
2.思路分析
递推公式 f[0] = f[0]
f[i] = f[i - 1] - sum(A) + A[i - 1] * N
3.参考代码
class Solution {
public int maxRotateFunction(int[] nums) {
int n = nums.length;
if (n == 0) return 0;
int sum = Arrays.stream(nums).sum();
int[] f = new int[n]; // 旋转函数
for (int i = 0; i < n; i++) {
f[0] += i * nums[i];
}
int res = f[0];
for (int i = 1; i < n; i++) {
f[i] = f[i - 1] - sum + n * nums[i - 1];
res = Math.max(f[i], res);
}
return res;
}
}
796. 旋转字符串
1.题目描述
leetcode链接:796. 旋转字符串
2.思路分析
方法一:子字符串
只需比较一下两个字符串的长度,然后判断A + A中是否存在B就ok,因为A + A中已经包含了所有可能的移动情况
方法二:模拟
首先,如果 s 和 goal 的长度不一样,那么无论怎么旋转,s 都不能得到 goa,返回 false。在长度一样(都为 n)的前提下,假设 s 旋转 i 位,则与 goal 中的某一位字符 goal[j] 对应的原 s 中的字符应该为 s[(i + j) mod n]
。在固定 i 的情况下,遍历所有 j,若对应字符都相同,则返回 true。否则,继续遍历其他候选的 i。若所有的 i 都不能使 s 变成 goal,则返回 false。
3.参考代码
方法一:子字符串
class Solution {
public boolean rotateString(String s, String goal) {
return s.length() == goal.length() && (s + s).contains(goal);
}
}
方法二:模拟
class Solution {
public boolean rotateString(String s, String goal) {
int m = s.length(), n = goal.length();
if (m != n) {
return false;
}
for (int i = 0; i < n; i++) {
boolean flag = true;
for (int j = 0; j < n; j++) {
if (s.charAt((i + j) % n) != goal.charAt(j)) {
flag = false;
break;
}
}
if (flag) {
return true;
}
}
return false;
}
}