赞
踩
定义:数组是存放在连续内存空间上的相同类型数据的集合,下标都是从0开始。
特点:连续 ==> 查找方便,新增/删除不方便【数组的元素是不能删的,只能覆盖】
前提:数组为有序数组 + 数组中无重复元素
难点:对区间的定义想清楚 ==》 保持不变量(在while寻找中每一次边界的处理都要坚持根据区间的定义来操作) ==》循环不变量规则
左闭右闭 [left, right]
范围包含right
left = right 时是有意义的,也就是在中间只有一个数的时候 ==》 while (left <= right)
左右边界变的时候要多移一位
左开右闭 [left, right) ==> while (left < right)
范围不包含right
left = right 时是没有意义的 ==》 while (left < right)
left需要多移动一位,right不需要,因为反正也不包含
相当于[1,2,3]和[1,2,3)的区别
示例:Java左闭右闭区间
- class Solution {
- public int search(int[] nums, int target) {
- // 避免当 target 小于nums[0] nums[nums.length - 1]时多次循环运算
- if (target < nums[0] || target > nums[nums.length - 1])
- return -1;
- int left = 0, right = nums.length - 1;
- while (left <= right) {
- int mid = left + ((right - left) >> 1);
- if (nums[mid] == target)
- return mid;
- else if (nums[mid] < target)
- left = mid + 1;
- else if (nums[mid] > target)
- right = mid - 1;
- }
- return -1;
- }
- }
时间复杂度:O(log n)
空间复杂度:O(1)
前提:数组中在保持基本顺序不变的前提下,删除指定元素(主要是减少空间复杂度)
难点:理解快慢指针的具体含义
快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
慢指针:指向更新 新数组下标的位置
示例:
- class Solution {
- public int removeElement(int[] nums, int val) {
- // 快慢指针
- int slowIndex = 0;
- for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) {
- if (nums[fastIndex] != val) {
- nums[slowIndex] = nums[fastIndex];
- slowIndex++;
- }
- }
- return slowIndex;
- }
- }
时间复杂度:O(n)
空间复杂度:O(1)
相关题目:
26. 删除有序数组中的重复项 - 力扣(LeetCode):额感觉没有用到快慢指针,如果前一项不等于这一项,那就要把这一项放进数组【有点绕】
- class Solution {
- public int removeDuplicates(int[] nums) {
- int next = 0;
- for (int i=1; i<nums.length;i++) {
- if (nums[i-1] != nums[i]) {
- next++;
- nums[next] = nums[i];
- }
- }
- return next + 1;
- }
- }
283. 移动零 - 力扣(LeetCode):先用快慢指针筛选出不含0的子数组,再在数组后面全部置0
- class Solution {
- public void moveZeroes(int[] nums) {
- int fast =0,slow=0;
- for (; fast < nums.length; fast++) {
- if(nums[fast]!=0){
- nums[slow]=nums[fast];
- slow++;
- }
- }
-
- // 后面置0
- for(int j = slow;j<nums.length;j++){
- nums[j]=0;
- }
- }
- }
844. 比较含退格的字符串 - 力扣(LeetCode):巧用StringBuilder,用append实现添加操作,deleteCharAt方法实现退格操作
- class Solution {
- public boolean backspaceCompare(String s, String t) {
- String processedS = processString(s);
- String processedT = processString(t);
-
- // 判断是否一致
- return processedS.equals(processedT);
- }
-
- private String processString(String str) {
- StringBuilder result = new StringBuilder();
-
- for (int i = 0; i < str.length(); i++) {
- char c = str.charAt(i);
- if(c!='#')
- result.append(c);
- else{
- // 注意这里要判断一下,否则超界Error
- if(result.length()!=0)
- result.deleteCharAt(result.length() - 1);
- }}
- return result.toString();
- }
- }
题目: 977. 有序数组的平方 - 力扣(LeetCode)
前提: 非递减顺序 排序
难点:非递减 ==》 平方大小两边向中间递减 ==》 对向双指针移动的逻辑
实现:
- class Solution {
- public int[] sortedSquares(int[] nums) {
- int p=nums.length-1;
- int[] arr=new int[nums.length];
- int left=0;
- int right=nums.length-1;
- while(left <= right){
- // 对向移动
- if(Math.abs(nums[left]) > Math.abs(nums[right])){
- arr[p]=nums[left] * nums[left];
- left++;
- }else{
- arr[p]=nums[right] * nums[right];
- right--;
- }
- p--;
- }
- return arr;
- }
- }
时间复杂度:O(n)
空间复杂度:O(1)
题目:209. 长度最小的子数组 - 力扣(LeetCode)
前提:问题涉及连续子数组或子字符串
难点:不断的调节子序列的起始位置和终止位置,注意for表示的是窗口的终止位置,每次for先确定终止位置再不断向前调整起始位置
滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)。
示例:
- class Solution {
- public int minSubArrayLen(int target, int[] nums) {
- int result = nums.length + 1;
- int sum = 0;
- int left = 0;
-
- // 滑动窗口,移动的是终止位置
- for (int i = 0; i < nums.length; i++) {
- sum += nums[i];
-
- while (sum >= target) {
- result = Math.min(result, i - left + 1);
- // 每次直接从确定的初始位置开始移动,因为是已经计算过的长度最短
- sum -= nums[left];
- left++;
- }
- }
- return result == nums.length + 1 ? 0 : result;
- }
- }
相关题目推荐:【还没做捏】
前提:好像没什么前提 本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/752971
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。