第一题-有序数组的平方
题目
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序
思路
因为刷题嘛,这个归到双指针的类别下,我就全部用的双指针,(用左右指针解释)
1、找到正负相交的那个节点为左指针,左指针加一为右指针,对比左右两边值的平方,小的放进结果里
- right为数组长度的时候,右指针已经遍历到末尾,但是左指针没有遍历结束,直接遍历左指针,把值塞到结果里
- 同理,当左指针小于0的时候,说明左边的已经遍历完毕,直接遍历右指针,塞到结果里。
- 剩下的情况就是对比左右两边的平方,哪边的小,先塞进结果了,然后继续遍历小的那边。
2、当然,这个也可以直接乘方,然后sort
代码
class Solution {
public int[] sortedSquares(int[] nums) {
int left = 0;
int n = nums.length;
for(int i = 0; i < n; i++) {
if(nums[i] < 0) {
left = i;
}else {
break;
}
};
int[] res = new int[n];
int right = left + 1;
int index = 0;
while(left >= 0 || right < n) {
if(right == n) {
int leftRes = nums[left] * nums[left];
res[index] = leftRes;
index++;
left--;
continue;
}
if(left < 0) {
int rightRes = nums[right] * nums[right];
res[index] = rightRes;
index++;
right++;
continue;
}
int leftRes = nums[left] * nums[left];
int rightRes = nums[right] * nums[right];
if(leftRes > rightRes) {
res[index] = rightRes;
index++;
right++;
continue;
}else {
res[index] = leftRes;
index++;
left--;
continue;
}
}
return res;
}
}
第二题-轮转数组
题目
给定一个整数数组 nums,将数组中的元素向右轮转 k **个位置,其中 k **是非负数
思路
1、遍历,整个数组遍历k%n遍,n是数组长度,可以说是暴力破解了
2、数组反转,三次反转就可以得到(可以理解成双指针)
代码
1、遍历
var rotate = function(nums, k) {
let n = nums.length - 1;
for(let i = 0; i < k % (n+1); i++) {
const last = nums[n];
for(let j = n; j >= 0; j--) {
if(j == 0) {
nums[j] = last;
}else {
nums[j] = nums[j -1 ];
}
}
}
return nums;
};
2、反转数组
/**
* start就是第一个指针,end是第二个指针
**/
const reverse = (nums, start, end) => {
while (start < end) {
const temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start += 1;
end -= 1;
}
}
var rotate = function(nums, k) {
k %= nums.length;
reverse(nums, 0, nums.length - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, nums.length - 1);
};
第三题-两数之和2-输入有序数组
题目
给你一个下标从 1 开始的整数数组 numbers ,该数组已按 ****非递减顺序排列 ** ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。
以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 **和 **index2。
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。
你所设计的解决方案必须只使用常量级的额外空间
思路
双指针,left为最左边的元素,right为最右边的元素,两个元素相加,要是大于目标元素,右指针左移,要是小于目标元素,左指针右移
代码
var twoSum = function(numbers, target) {
let left = 0;
let right = numbers.length -1;
while(left < right) {
if(numbers[left] + numbers[right] > target) {
right--;
}else if(numbers[left] + numbers[right] < target) {
left++;
}else {
break;
};
};
return [left+1, right+1];
};
第四题-反转字符串
题目
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组**、使用 O(1) 的额外空间解决这一问题
思路
和第二题的反转数组一个性质,两个指针分别在两边,然后互换元素值,继续遍历
代码
var reverseString = function(s) {
let left = 0;
let right = s.length - 1;
while(left < right) {
const flag = s[left];
s[left] = s[right];
s[right] = flag;
left++;
right--;
}
return s;
};
第五题-反转字符串中的单词
题目
给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序
思路
(悄悄说一句,使用js写算法,动不动就超时,动不动就超时,不知道是我的问题,还是js拉垮,真讨厌啊) 1、分解字符串为数组(空格为间隔)
2、遍历分解字符串后形成的数组
3、数组中每个元素再次进行分解(因为字符串是不可变的,只能分解成数组,操作替换,再合成字符串)
4、第三步中的操作替换就是第二题的反转数组思路
代码
var reverseWords = function(s) {
let sArr = s.split(" ");
for(let i = 0; i < sArr.length; i++) {
let left = 0;
let sArrIArr = sArr[i].split('');
let right = sArrIArr.length - 1;
while(left < right) {
const flag = sArrIArr[left];
sArrIArr[left] = sArrIArr[right];
sArrIArr[right] = flag;
left++;
right--;
};
sArr[i] = sArrIArr.join('');
};
return sArr.join(" ");
};
第六题链表的中间节点
题目
给定一个头结点为 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点
思路
双指针之快慢指针,快慢指针,链表题经常用到的算法
1、low为慢指针,每次走一步,fast为快指针,每次走两步,当fast走到最后时候,low必然走在中间
代码
var middleNode = function(head) {
let low = head;
let fast = head;
while(fast != null) {
if(fast.next != null) {
low = low.next;
fast = fast.next.next;
}else {
break;
}
}
return low;
};
第七题-删除链表的倒数第n个节点
题目
给你一个链表,删除链表的倒数第 n **个结点,并且返回链表的头结点
思路
1、借助栈-弹出栈的第 n 个节点就是需要删除的节点
2、双指针-直接上代码吧,我看官方文字描述好多,脑袋疼
- 先让第一个指针走,走n步
- 第一个指针走完n步后,两个指针一起走,一直走到第一个指针已经到最后的时候,第二个指针的next就是要删除的节点(因为第一个指针比第二个指针快n步啊)
代码
1、栈
var removeNthFromEnd = function(head, n) {
const stack = [];
let headCopy = new ListNode(0, head);
let cur = headCopy;
while(cur != null) {
stack.push(cur);
cur = cur.next;
}
for(let i = 0; i < n; i++) {
stack.pop();
};
const res = stack.pop();
res.next = res.next.next;
stack.push(res)
let resLast = headCopy.next;
return resLast;
};
2、双指针
var removeNthFromEnd = function(head, n) {
let res = new ListNode(0, head);
let first = head;
let second = res;
for(let i = 0; i < n; i++) {
first = first.next;
}
while(first != null) {
first = first.next;
second = second.next;
}
second.next = second.next.next;
return res.next;
};