当前位置: 首页 > news >正文

算法_记忆知识点汇总

1.二分法中,left要0,right要length-1    但是mid是(left+right)/2,不需要减一

2.二分法_旋转数组,查找数组的旋转点:要right=mid,而不能像普通的二分法那样right=mid-1.因为mid-1可能会跳过旋转点。

3.二分法:搜索回旋数组,要找最小值,而不是最大值。为什么left=mid+1但是right=mid?因为,nums[mid]如果>nums[right],那么这个最小值,也就是我们最后要找的那个值,一定是在这个mid索引的右边,说白了, 这个mid索引是不可能的。 而如果要是nums[mid]<nums[right],那我们要找的那个值,可能是这个mid。如果贸然把这个mid-1传给right。很可能会错过的。

复制数组:Arrays.copyOfRange(nums,start,end); 左开右闭。

Arrays.copyOfRange(nums,0,0);不会报错,创建了一个空数组,但是Arrays.copyOfRange(nums,0,-1);就会报错了

对链表的排序是归并排序。

短路求值!

if(minStack.isEmpty() || val <= minStack.peek())

正常来说,这个minStack.peek()当minStack为空的时候,会报错。可是我们前面有个判空。如果为空,后面的条件会短路,因此跳过了。就不会出问题了。

public void pop() {if(stack.pop().equals(minStack.peek())) {  // 这里已经执行了stack.pop()minStack.pop();}// 不需要再写stack.pop(),因为上面已经pop过了
}

每日温度那个题,最优算法用的是Stack栈

Stack线程安全,Dequeue线程不安全。Dequeue是用安全性换了性能。

堆:完全二叉树。有大根堆、小根堆

1.数组连续值最大

轮转数组的索引index是i-k。

//轮转数组的索引index是i-k。因为第零个位置,它对应的数字应该是某个数字前进了三个之后才到第零个位置的。所以,这个数字应该是从index 0 往前找三个位置。也就是0 -1 -2 -3也就是对应的:0 7 6 5.所以是i-k

//前缀积   后缀积   只需要前后遍历一遍就行。 遍历前缀积的时候,不需要for循环。只需要用当前元素的前一个*前一个元素的前缀积就行了

                //O2n、、、O3n   也都是On

一般寻找第几大的元素,无论这个元素是否重复,都会用小根堆来解决问题。

因为直接遍历,一次只能找

关于时间复杂度

O2n是On。

Okn不是On

如果Okn中的k是固定的,像2一样,2是固定的,那么这个Okn就是On

减枝算法:用if排除掉某些情况,从而减少计算量。

sort方法的时间复杂度是Onlogn    

如果在一个算法前面用了一次sort,后面又用了一次On的算法。那么这个算法的总时间复杂度是Onlogn

如果前面用了sort,后面用了On²的算法,那么这个算法的总时间复杂度是On²

索引越界不仅仅是往上越界,还可能是往下越界。

Set<List<Integer>>  set = new HashSet<>(list);
List<List<Integer>> res= new ArrayList<>(set);

不用add,直接成List 的方法:

Arrays.asList(a,b,c,d,e,f,g);

一个小小的else,可能导致整个算法的错误。上面代码有else,下面代码没有else。力扣:三数之和

class Solution {public List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> res = new ArrayList();if(nums==null){return res;}Arrays.sort(nums);for(int i =0;i<nums.length;i++){if(i>0&&nums[i] == nums[i - 1]){continue;}int a = nums[i];int left =i+1;int right = nums.length-1;while(left<right){int sum = a + nums[left]+nums[right];if(sum==0){/*List<Integer> array = new ArrayList<>();array.add(nums[i]);array.add(nums[left]);array.add(nums[right]);res.add(array);*/res.add(Arrays.asList(nums[i],nums[left],nums[right]));/*if (nums[left]==nums[left-1]) {//这个循环中,左右指针没有变化,所以导致。每一次传进while循环里面都是相同的left right i。因此无限循环。//要加上left++才行continue;}*/while(left<right&&nums[left]==nums[left+1]){left++;}while(left<right&&nums[right]==nums[right-1]){right--;}left++;right--;}else if(sum<0){left++;}else{right --;}}}//有重复,需要对res去重//Set<List<Integer>> set = new HashSet<>(res);//List<List<Integer>> list = new ArrayList<>(set);return res;}
}
class Solution {public List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> res = new ArrayList();if(nums==null){return res;}Arrays.sort(nums);for(int i =0;i<nums.length;i++){if(i>0&&nums[i] == nums[i - 1]){continue;}int a = nums[i];int left =i+1;int right = nums.length-1;while(left<right){int sum = a + nums[left]+nums[right];if(sum==0){/*List<Integer> array = new ArrayList<>();array.add(nums[i]);array.add(nums[left]);array.add(nums[right]);res.add(array);*/res.add(Arrays.asList(nums[i],nums[left],nums[right]));/*if (nums[left]==nums[left-1]) {//这个循环中,左右指针没有变化,所以导致。每一次传进while循环里面都是相同的left right i。因此无限循环。//要加上left++才行continue;}*/while(left<right&&nums[left]==nums[left+1]){left++;}while(left<right&&nums[right]==nums[right-1]){right--;}left++;right--;}if(sum<0){left++;}else{right --;}}}//有重复,需要对res去重//Set<List<Integer>> set = new HashSet<>(res);//List<List<Integer>> list = new ArrayList<>(set);return res;}
}

 滑动窗口:特殊形式的双指针

二叉树和图的DFS用递归。需要在一条路径上跑完,确定这条路径到底行不行

二叉树和图的BFS用队列实现。一般用于感染。

回溯算法:是要回溯到传入这一层之前的状态。

递归和二叉树有什么不同呢?其实递归它像是:只在叶节点上存放return结果的二叉树。

而二叉树在每个节点都存放。

找零钱  算法   用的是DP,而不是贪心算法。

做的不错的地方:第一次看题目就想到了颜色分类算法的最有解,只遍历一遍数组且思路方向对。但是具体实施细节有误。

三路指针快速排序,三个指针实际上有点类似隐式复制了三组数组。只是这三组数组不用画出来,用指针就行。因此,当第一个元素和第一个元素交换的时候,其实是cur指针对应的数组和left指针对应的数组的交换。

如果算法看不懂,就带入几个测试用例看看。

dfs(n,++left,right,tmp);是先执行left++再执行函数

dfs(n,left++,right,tmp);是先执行函数再left++

力扣 T22 括号生成

class Solution {List<String> res = new ArrayList<>();public List<String> generateParenthesis(int n) {String tmp ="" ;dfs(n,0,0,tmp);return res;}public void dfs(int n , int left , int right , String tmp){if(left==n&&right==n){res.add(tmp);    return;}if(left<n){//这里的left++了,但是我们没有给它回溯,因此这里正确的写法不是left++,而是left+1tmp = tmp+'(';dfs(n,++left,right,tmp);tmp = tmp.substring(0,tmp.length()-1);}if(right<left){tmp = tmp+')';dfs(n,left,++right,tmp);tmp = tmp.substring(0,tmp.length()-1);}}
}

回溯是回溯到进入这层之前的状态

return 结束的仅仅是当前层

class Solution {public boolean exist(char[][] board, String word) {//recordint rows = board.length;int cols = board[0].length;boolean[][] barray = new boolean[rows][cols];for(int i = 0;i<rows;i++){for(int j =0;j<cols;j++){boolean res = dfs(i,j,0,board,word,barray);if(res == true){return true;}}}return false;}public boolean dfs(int row ,int col ,int index,char[][] board, String word,boolean[][] barray){//boardthif(index == word.length()){return true;}//recordint rows = board.length;int cols = board[0].length;//condition and judge itif(row<0 || row>=rows || col<0 || col>=cols || barray[row][col]==true || board[row][col]!=word.charAt(index)){return false;}//renew the barraybarray[row][col] = true;//recursionboolean res = false;res |= dfs(row+1,col,index+1,board,word,barray);res |= dfs(row,col+1,index+1,board,word,barray);res |= dfs(row-1,col,index+1,board,word,barray);res |= dfs(row,col-1,index+1,board,word,barray);//backtrackingbarray[row][col] = false;return  res;}
}

这个代码的一个思想是:index是当前元素索引,判断字符是否相等用的是index,为什么最后判断index和word.length()相等与否用的也是index而不是index+1呢?是因为res |= dfs(row-1,col,index+1,board,word,barray);的时候已经给index+1了。因此一定能够走到index+1的长度。也就是实际上这个inde一共走了length+1步。也就是索引从0到length。

可以用|=布尔值来代替用for + if 循环判断

        res |= dfs(row+1,col,index+1,board,word,barray);
        res |= dfs(row,col+1,index+1,board,word,barray);
        res |= dfs(row-1,col,index+1,board,word,barray);
        res |= dfs(row,col-1,index+1,board,word,barray);

判断是否为回文串:用的是左右双指针

多维动态规划:不同路径  核心思想:f(m*n)=f(m*(n-1))+f((m-1)*n)

用二维数组保存起来

一种递归中类似树的很重要的思想。一共六个空位,0+6,1+5,2+4,3+3,4+2,5+1,6+0互不包含,因此必定互斥,因此可以分别进行递归。

典型例题:力扣leetcode131   分割回文串

//所有动态规划的dp其实都有一个基准值,那么这个题的基准值不是每个币对应1,而是这个dp[0],且只有这个dp[0],其他包括 币对应的1  都是在这个基准值0的基础上迭代的。

class Solution {//动态规划中很有意思的现象是,我们把for循环时候,int i =1;i<=mount而不再是<,并且不再是int i = 0了public int coinChange(int[] coins, int amount) {int n = amount;int[] dp = new int[amount+1];for(int i =1;i<=n;i++){dp[i] = amount+1;}//所有动态规划的dp其实都有一个基准值,那么这个题的基准值不是每个币对应1,而是这个dp[0],且只有这个dp[0],其他包括 币对应的1  都是在这个基准值0的基础上迭代的。dp[0] = 0;for(int i = 1;i<=amount ; i++){for(int coin:coins){int tmp = i-coin;if(tmp>=0){dp[i] = Math.min(dp[tmp]+1,dp[i]);}}}return dp[amount]<=amount? dp[amount]:-1;}
}

http://www.dtcms.com/a/500400.html

相关文章:

  • 网站下载织梦模板潍坊网站排名公司
  • cnzz网站代做百度官方下载安装
  • (2)路由表
  • 电商网站开发需要掌握哪些知识技能设计一个企业网站报价
  • 做平面资源比较好的网站安卓优化清理大师
  • 公司做网站好豌豆荚应用商店
  • C++----继承
  • 制作表白网站的软件长链接转化成短链接
  • 服装网站的设计理念wordpress 知识库模板
  • SAP_MM_供应商寄售 ( Vendor Consignment ) 实施流程
  • HTML的盒子模型
  • 九狐建设网站做58网站怎么赚钱
  • 股骨转子间骨折
  • 怎么破解别人做的付费网站互联网保险的定义
  • 泰州网站建设费用福建建设厅网站 资质
  • 做网站潍坊绍兴网站建设解决方案
  • 商城形式的网站需要多少钱wordpress single page
  • wordpress怎么给网站设置几种语言网站建设一般多少钱要如何选择
  • 实用设计网站推荐撰写网络推广策划案
  • 昆明网站seo多少钱网站关键字 优帮云
  • Effective STL 第5条:区间成员函数优先于单元素成员函数
  • app开发与网站建设难度四川省建设厅官方网站扣分记录
  • 参考效果图网站建设网站挣钱
  • 网站建设中网站图片如何修改1688官网商家版
  • 游戏网站免费入口已申请域名怎么做网站
  • 苏州网站推广去苏州聚尚网络做网站公司找哪家
  • php 网站 教程wordpress文章id连续
  • Redis 自动化脚本安装方案
  • 建站的cms哪个网站做图找图片
  • 网站域名续费后SEO查询未更换科技小巨人申报条件