力扣算法题
1、27. 移除元素
审题很关键啊,读不懂题目或者一知半解都不要敲代码,思路比代码更重要,好好读读题意思也挺明显,让你返回一个len,代表移除完毕后的数组长度,要求数组下标为0到len-1的元素都是没删除的元素。
一开始思路也不是很清晰,感觉应该有比较巧妙的方法,最后也没想出来,弄了个新数组记录一下原数组保留的元素,然后copy到原数组,过了。
Arrays.copyOfRange([] original, int from, int to)
参数:
original:要拷贝的数组对象
from:为拷贝的开始位置(包含)
to:拷贝的结束位置(不包含)
public int removeElement(int[] nums, int val) {
int ans = nums.length, j = 0;
int[] temp = nums;
for(int i = 0; i < nums.length; i++){
if(nums[i] == val){
ans--;
}
else{
temp[j++] = nums[i];
}
}
nums = Arrays.copyOfRange(temp, 0, ans);
return ans;
}
果然有更优雅的解决方法:
class Solution {
public int removeElement(int[] nums, int val) {
int len = nums.length, i = 0;
while(i < len){
if(nums[i] == val){
nums[i] = nums[len-1];
len--;
}
else{
i++;
}
}
return len;
}
}
len代表最终数组长度,一开始等于原数组长度,遍历数组,每当遇到应该删除的元素,就把最后一个元素赋值给当前元素,然后减小len;否则,该元素就应该保留,i++。这样,后面的元素如果也是应该删除的元素就会一直删除,因为i一直不变。
2、977. 有序数组的平方
暴力:遍历一下再排个序,快排时间复杂度nlogn
public int[] sortedSquares(int[] nums) {
// 遍历一下再排个序
for(int i = 0; i < nums.length; i++){
nums[i] = nums[i] * nums[i];
}
Arrays.sort(nums);
return nums;
}
还有一种双指针的解法:
观察nums数组,平方后最大值一定从两侧取,所以可以设置两个首尾指针,倒着添加到一个新数组中。i,j是首位指针,index记录新数组ans的下标。时间复杂度O(n)
class Solution {
public int[] sortedSquares(int[] nums) {
int i = 0, j = nums.length-1;
int index = nums.length-1;
int[] ans = new int[nums.length];
while(index >= 0){
if(nums[i]*nums[i] > nums[j]*nums[j]){
ans[index--] = nums[i]*nums[i];
i++;
}
else{
ans[index--] = nums[j]*nums[j];
j--;
}
}
return ans;
}
}
3、209. 长度最小的子数组
真的不想再暴力啦!
本题思路是如何把双层for循环优化成一个for循环,还是利用双指针,单层for循环的j代表尾指针,每次移动后都记录从i到j的和,如果和大于目标值,就更新ans,直到找到最小的ans。
public int minSubArrayLen(int target, int[] nums) {
int i = 0, ans = Integer.MAX_VALUE, temp = 0;
for(int j = 0; j < nums.length; j++){
temp += nums[j];
System.out.println(temp);
while(temp >= target){
ans = (j-i+1)<ans ? (j-i+1) : ans;
temp -= nums[i];
i++;
}
}
return ans==Integer.MAX_VALUE?0:ans;
}
4、59. 螺旋矩阵 II
记得之前刷刘汝佳紫书就有这个题,叫蛇形矩阵,这种题属于模拟题,但是一定要充分考虑边界问题,自己搞了一个小时才搞出来,主要是思路太不清晰了。
以4*4举例,一开始我是这么找的,边界判断的稀碎
四条边可以统一用这种左闭右开的找法,这样就能在每一圈的循环中统一判断四个边的各种情况,而不是外圈判断好了,内圈又出问题了。
如下代码,cnt代表填充的数字。因为每圈都要缩小,所以定义了一个变量t,用来控制边界。(一开始忘记每次循环令t++,找了半个小时bug)。
内圈四个for循环则是用来填充上、右、下、左的值。仔细找找其中的规律,写出来并不难。
最后判断n是不是奇数,是奇数要把中间手补上。
class Solution {
public int[][] generateMatrix(int n) {
int[][] a = new int[n][n];
int i = 0, j = 0, t = 1, cnt = 1;
for(int r = 0; r < n/2; r++){
for(j = r; j < n-t; j++){
System.out.println("1r: " + r + " j: " + j);
a[r][j] = cnt++;
System.out.println("a[r][j]: " + a[r][j]);
}
for(i = r; i < n-t; i++){
System.out.println("2r: " + r + " i: " + i);
a[i][j] = cnt++;
System.out.println("a[i][j]: " + a[i][j]);
}
for(; j >= t; j--){
System.out.println("3r: " + r + " j: " + j);
a[i][j] = cnt++;
System.out.println("a[i][j]: " + a[i][j]);
}
for(; i >= t; i--){
System.out.println("4r: " + r + " i: " + i);
a[i][j] = cnt++;
System.out.println("a[i][j]: " + a[i][j]);
}
t++;
}
if(n%2==1) a[n/2][n/2] = n*n;
return a;
}
}