*二分查找
题目链接
https://leetcode.cn/problems/binary-search/
左闭右闭区间实现
- 时间复杂度:O(log n)
- 空间复杂度:O(1)
/*** 左闭右闭写法** @param nums* @param target* @return*/
public static int search1(int[] nums, int target) {if (nums == null || nums.length == 0) {return -1;}int left = 0;int right = nums.length - 1;// 要是没有等号的话,在{5}里面找5就会出问题了while (left <= right) {int center = (left + right) / 2;if (target == nums[center]) {return center;} else if (target > nums[center]) {left = center + 1;} else {right = center - 1;}}return -1;
}
左闭右开区间实现
- 时间复杂度:O(log n)
- 空间复杂度:O(1)
/*** 左闭右开写法** @param nums* @param target* @return*/
public static int search2(int[] nums, int target) {if (nums == null || nums.length == 0) {return -1;}int left = 0;// 区别点int right = nums.length;// 区别点while (left < right) {int center = (left + right) / 2;if (target == nums[center]) {return center;} else if (target > nums[center]) {left = center + 1;} else {// 区别点// 虽然已经知道center位置的元素不是要找的元素,但是因为是左闭右开,因此right还是指向center// 后面无论怎么循环,都不会再使用到center这个为止,因为center = (left + right) / 2永远小于rightright = center;}}return -1;
}
*移除元素
题目链接
https://leetcode.cn/problems/remove-element/
暴力求解
- 时间复杂度:O(n^2)
- 空间复杂度:O(1)
public static int removeElement(int[] nums, int val) {int sameNum = 0;int i = 0;while (i < nums.length - sameNum) {if (val == nums[i]) {// 将后面的元素前移过来for (int j = i; j < nums.length - 1 - sameNum; j++) {nums[j] = nums[j + 1];}sameNum++;}if (val == nums[i]) {// 前移过来的数值和val一样,将i--i--;}i++;}return nums.length - sameNum;
}
双指针
- 时间复杂度:O(n)
- 空间复杂度:O(1)
【思想】
通过一个快指针和慢指针在一个for循环下完成两个for循环的工作,将快指针的值赋给慢指针
slow:新数组存储值的索引,因为每次存储完新数组的值,都会将slow++,因此最后直接返回slow即可,需要返回slow+1
fast:用来去前面探索那些不是val的值,然后将这个值赋给slow对应的位置
/*** 双指针** @param nums* @param val* @return*/
public static int removeElement1(int[] nums, int val) {int slow = 0;for (int fast = 0; fast < nums.length; fast++) {if (nums[fast] != val) {// 如果快指针找的数值不是val,就需要将其存储到新数组中// 同时slow++,以便存储下一个新数组的值nums[slow++] = nums[fast];}}return slow;
}
相向双指针法
- 时间复杂度:O(n)
- 空间复杂度:O(1)
上面的实现方法并没有改变元素的相对位置,相向双指针方法改变了元素相对位置,但是确保移动最少元素
/*** 想向双指针** @param nums* @param val* @return*/
public static int removeElement(int[] nums, int val) {int slow = 0, fast = nums.length - 1;while (slow <= fast) {// slow赋值为第一个等于val的索引while (slow <= fast) {if (nums[slow] != val) {slow++;} else {break;}}// fast赋值为最后一个等于val的索引while (fast >= slow) {if (nums[fast] == val) {fast--;} else {break;}}if (slow < fast) {nums[slow++] = nums[fast--];}}// slow最后一定指向的是 新数组末尾元素的下一个元素return slow;
}
*有序数组的平方
题目链接
https://leetcode.cn/problems/squares-of-a-sorted-array/
暴力求解
- 先对数组的每个元素求平方
- 对数组升序排序
时间复杂度:O(n)+排序算法的时间复杂度
双指针
【思路】
数组本身就是非递减顺序的,只不过负数在平方之后可能会变大,因此只需要用两端来比较就能知道那个数字的平方更大
- 时间复杂度:O(n)
- 空间复杂度:O(n)
public static int[] sortedSquares(int[] nums) {int left = 0, right = nums.length - 1;// 用于存储排序之后的结果int[] result = new int[nums.length];for (int i = nums.length - 1; i >= 0; i--) {int leftValue = nums[left];int rightValue = nums[right];if (leftValue * leftValue >= rightValue * rightValue) {result[i] = leftValue * leftValue;left++;} else {result[i] = rightValue * rightValue;right--;}System.out.println(Arrays.toString(result));}return result;
}
*长度最小的子数组
题目链接
https://leetcode.cn/problems/minimum-size-subarray-sum/
暴力求解
- 时间复杂度:O(n^2)
- 空间复杂度:O(1)
注意,子数组是原数组中连续的几个元素的集合
public int minSubArrayLen(int target, int[] nums) {// 最小子数组长度int minLen = nums.length + 1;for (int i = 0; i < nums.length; i++) {int sum = 0;for (int j = i; j < nums.length; j++) {sum += nums[j];if (sum >= target) {// 已经>=target,可以暂停了if ((j - i + 1) < minLen) {minLen = j - i + 1;break;}}}}return minLen == nums.length + 1 ? 0 : minLen;
}
部分案例已经超出时间限制
滑动窗口
- 时间复杂度:O(n):不能以为for里放一个while就是O(n^2), 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)
- 空间复杂度:O(1)
/*** 滑动窗口** @param target* @param nums* @return*/
public int minSubArrayLen1(int target, int[] nums) {// 最小子数组长度int minLen = nums.length + 1;int i = 0;int sum = 0;for (int j = 0; j < nums.length; j++) {// j++,窗口终止位置后移一位,sum添加相应的元素sum += nums[j];while (sum >= target) {// 窗口内的元素总和已经超过target,尝试将窗口的起始位置后移,即i++if ((j - i + 1) < minLen) {minLen = j - i + 1;}// sum移除窗口起始位置的元素值sum -= nums[i++];}}return minLen == nums.length + 1 ? 0 : minLen;
}
螺旋矩阵
【思想】
这道题主要是考代码能力,注意每次循环都是左开右闭就行
【我写的程序】
public static int[][] generateMatrix1(int n) {int[][] result = new int[n][n];int curNum = 1;int target = n * n;int initN = n;// 圈数int cirCleNum = 0;while (curNum <= target) {if (curNum == target) {result[cirCleNum][cirCleNum] = curNum;System.out.println("---------------------填中心---------------------");for (int i = 0; i < result.length; i++) {System.out.println(Arrays.toString(result[i]));}break;}// 填上边for (int i = 0; i < n - 1; i++) {result[cirCleNum][i + cirCleNum] = curNum++;}System.out.println("---------------------填上边---------------------");for (int i = 0; i < result.length; i++) {System.out.println(Arrays.toString(result[i]));}// 填右边for (int i = 0; i < n - 1; i++) {result[i + cirCleNum][initN - 1 - cirCleNum] = curNum++;}System.out.println("---------------------填右边---------------------");for (int i = 0; i < result.length; i++) {System.out.println(Arrays.toString(result[i]));}// 填下边for (int i = n - 1; i > 0; i--) {result[initN - 1 - cirCleNum][i + cirCleNum] = curNum++;}System.out.println("---------------------填下边---------------------");for (int i = 0; i < result.length; i++) {System.out.println(Arrays.toString(result[i]));}// 填左边for (int i = n - 1; i > 0; i--) {result[i + cirCleNum][cirCleNum] = curNum++;}System.out.println("---------------------填左边---------------------");for (int i = 0; i < result.length; i++) {System.out.println(Arrays.toString(result[i]));}System.out.println("======================================================================");cirCleNum += 1;n -= 2;}return result;
}
【别人的代码】
public int[][] generateMatrix(int n) {int loop = 0; // 控制循环次数int[][] res = new int[n][n];int start = 0; // 每次循环的开始点(start, start)int count = 1; // 定义填充数字int i, j;while (loop++ < n / 2) { // 判断边界后,loop从1开始// 模拟上侧从左到右for (j = start; j < n - loop; j++) {res[start][j] = count++;}// 模拟右侧从上到下for (i = start; i < n - loop; i++) {res[i][j] = count++;}// 模拟下侧从右到左for (; j >= loop; j--) {res[i][j] = count++;}// 模拟左侧从下到上for (; i >= loop; i--) {res[i][j] = count++;}start++;}if (n % 2 == 1) {res[start][start] = count;}return res;
}