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

公司网站建设找谁百度公司

公司网站建设找谁,百度公司,网页版微信无法登录,mip网站怎么做匹配文章目录 前言组合总和问题分割回文串子集问题排序问题字母大小写全排列单词搜索总结 前言 提示:我不愿再给你写信了。因为我终于感到,我们的全部通信知识一个大大的幻影,我们每个人知识再给自己写信。 --安德烈纪德 回溯主要解决一些暴力枚举…

文章目录

  • 前言
  • 组合总和问题
  • 分割回文串
  • 子集问题
  • 排序问题
  • 字母大小写全排列
  • 单词搜索
  • 总结


前言


提示:我不愿再给你写信了。因为我终于感到,我们的全部通信知识一个大大的幻影,我们每个人知识再给自己写信。 --安德烈·纪德

回溯主要解决一些暴力枚举也搞不定的问题,例如组合、分割、子集、排列、棋盘等。这关我们就看看如何接入。

组合总和问题

参考题目地址:39. 组合总和 - 力扣(LeetCode)

在这里插入图片描述
如过不考虑重复的,这个题目和113的那个题目相差无疑,如果可以重复,哪呢是否可以无限制取下去呢?也不会,因为题目也给了说明。每个元素最小为1,因此最多一个target个1.我们画图该怎么做呢,对于序列{2,3,6,7}.target = 7.很明显我们选择1个2,还剩下target = 7 - 2 = 5.然后再选取一个2,还剩下target = target - 2 = 3;之后再选一个2,变成了target = target - 2 = 1,此时最小的为2,不能再选了,就要退出。看看有没有3。ok,有那么第一个结果就是{2,2,3}.

之后我们继续回退到只选1个2的时候,这是2不能选了,从{3,6,7}中选择,如下图所示,没有符合规定的。

依次类推,然后尝试从3和6、7中开始选择。

最终的结果就是{2,2,3}和{2,5}.为了方便,我们可以先对元素做个排序,然后按照上面的过程执行,形成一个树形图:

在这里插入图片描述
这个图横向是针对每个元素做暴力枚举,纵向是递归(向下找)也是纵横问题,实现起来代码也不复杂:

public List<List<Integer>> combinationSum(int[] c, int target) {List<List<Integer>> res = new ArrayList();List<Integer> path = new ArrayList();dfs(c,0,target,path,res);return res;
}public void dfs(int[] c,int u,int target,List<Integer> path,List<List<Integer>> res){if(target < 0){return;}if(target == 0){res.add(new ArrayList(path));return;}for(int i = u; i < c.length; i++){if(c[i] <= target){path.add(c[i]);dfs(c,i,target - c[i],path,res);path.remove(path.size() - 1);}   }
}

分割回文串

参考题目地址:131. 分割回文串 - 力扣(LeetCode)

在这里插入图片描述
字符串如何判断回文本身就是一道算法题,本题在其之上还要解决一个问题:如何分割?如果暴力切割很麻烦,解决起来也很困难,如果从回溯的角度去思考就很清晰:
在这里插入图片描述
我们说回溯本身仍然回进行枚举的,这里也是一样的。切割线(途中的|)切割到字符串的结尾位置,说明找到了一个切割方法。这里就是先试一试,第一次切割’a’,第二次切割’aa‘,第三次切割’aab’。这对应的就是回溯里面的for循环(也就是横向遍历)

我们还要说回溯(需要进行递归操作)第一次切合’a’,剩下的就是‘ab’.递归就是在将其且下一个回文下来,也就是第二个‘a’,剩下的‘b’再交给递归进行一步切割。这就是纵向方面要干的事,依次类推。

至于回溯操作与前面的一样的道理,不再赘述。通过代码就可以发现,切割问题的回溯搜索的过程和嘴和问题的回溯搜索的过程是差不多的。

class Solution {List<List<String>> res = new ArrayList<>();Deque<String> path = new LinkedList<>();public List<List<String>> partition(String s) {backTracking(s,0);return res;}private void backTracking(String s, int startIndex) {// 如果起始位置大于s的大小,说明找到了一组分割方案if (startIndex >= s.length()) {res.add(new ArrayList<>(path));return;}for (int i = startIndex; i < s.length(); i++) {// 如果是回文子串,则记录if (isPalindrome(s, startIndex, i)) {String str = s.substring(startIndex, i + 1);path.addLast(str);} else {continue;} // 起始位置后移,保证不重复backTracking(s, i + 1);path.removeLast();}}public boolean isPalindrome(String str,int start,int end){for(int i = start, j = end; i < j; i++,j--){if(str.charAt(i) != str.charAt(j)){return false;}}return true;}
}

子集问题

子集问题也是回溯的经典使用场景。回溯可以画成一种状态树,子集,组合,分割,都可以抽象出来。

但是子集也有它特有的类型:需要找出所有情况。

参考题目:78. 子集 - 力扣(LeetCode)

在这里插入图片描述
在这里插入图片描述
画图详解:
在这里插入图片描述
从图中也可以看出,遍历这颗树的时候,就可以记录下所有的节点,也就是得到子集结果。

那么什么时候停下来呢?起始可以不加终止条件,因为startIdex >= nums.size(),for循环就结束了。

记住:求子集问题,不需要任何的剪枝操作!因为子集就是要遍历整颗树。这样实现起来也比较容易。

class Solution {List<List<Integer>> res = new ArrayList<>();List<Integer> path = new ArrayList();public List<List<Integer>> subsets(int[] nums) {// 空集也是if(nums.length == 0 ){res.add(new ArrayList<>());return res;}backTracking(nums,0);return res;} public void  backTracking(int[] nums,int startIndex){// 记住:加进来,再判断res.add(new ArrayList(path));if(startIndex >= nums.length){return;}for(int i = startIndex; i < nums.length; i++){// 今典小连招path.add(nums[i]);backTracking(nums,i+ 1);path.remove(path.size() - 1);}}
}

tips:上面的代码可以通过全局定义res和path,这样简介。这里(也可以转成参数传递的形式)

排序问题

参考题目介绍:46. 全排列 - 力扣(LeetCode)

在这里插入图片描述

排列问题也是经典的问题(每次刷是不是都难)。这个问题和前面的组合等问题的一个区别就是后面的还用再选(可重复),例如:1:开始使用了,但是到了2和3的时候仍然要使用一次。本质上是因为【1,2】和【2,1】从集合的角度看一个问题,单是从排列的角度是两个问题。

元素1在【1,2】中已经使用多了,但是在【2,1】中还要再使用一次,所以就不能使用startIndex了,此时可以使用一个used数组来标记已经选择的元素,完整的过程如图所示:

在这里插入图片描述
开图就知道了,怎么确定终止条件呢?就是到达叶子节点,那么是么时候到达叶子节点呢?

当时收集元素的数组path的大小达到和nums数组一样不就行了,说明就找到了一个全排列,也就是到达叶子节点了。

class Solution {List<List<Integer>> res = new ArrayList<>();List<Integer> path = new ArrayList<>();// 是否选boolean[] used ; public List<List<Integer>> permute(int[] nums) {if(nums.length == 0){return res;}used = new boolean[nums.length];permuteHepler(nums);return res;}public  void permuteHepler(int[] nums){if(path.size() == nums.length){res.add(new ArrayList<>(path));return ;}for(int i = 0; i < nums.length; i++){//  解决01 10 问题if(used[i]){continue;}used[i] = true;path.add(nums[i]);permuteHepler(nums);//  经典回溯path.remove(path.size() - 1);used[i] = false;}}
}

字母大小写全排列

参考题目地址:784. 字母大小写全排列 - 力扣(LeetCode)

在这里插入图片描述

如果本题去掉数组,只告诉你两个字母ab,然你每个字母变化大小写,那么就是ab,Ab,aB,AB四种情况。就和上面的处理一样了。这里有数字的干扰,我们就需要作过滤数字,只处理字母。还有就是添加大小写的转换问题了。
在这里插入图片描述

由于每个字符的大小形式刚好相差32,因此再大小写里面可以换成用c^32来进行转换和恢复。这样代码就简洁多了:

class Solution {List<String> res = new ArrayList<>();public List<String> letterCasePermutation(String s) {dfs(s.toCharArray(),0);return res;}public void dfs(char[] arr, int pos){// 过滤数字while(pos < arr.length && Character.isDigit(arr[pos])){pos++;}// 终止条件if(pos == arr.length){res.add(new String(arr));return;}// 转换arr[pos]^=32;dfs(arr,pos + 1);// 撤销arr[pos]^=32;dfs(arr,pos + 1);}
}

单词搜索

参考题目介绍:79. 单词搜索 - 力扣(LeetCode)

在这里插入图片描述

在这里插入图片描述

思路:从上到下,左到右遍历网格,每个坐标递归调用check(i,j,k)函数,i,j表示网格坐标,k表示word的第k个字符,如果能搜索到第k个字符返回true,否则返回false。

check函数的终止条件也很明确:

  1. 如果i,j的位置和字符上的字符位置k不相符,也就是说这个方面的路径有问题,直接返回false
  2. 如果搜索到了字符串的结尾,则找到了网格中的一条路径,这条路径上的字符正好可以组成字符串s,返回true。

两种情况都不满足,就把当前网格加入visited数组,visited表示该位置已经访问过了,然后顺着当前网格的坐标的四个方向继续尝试,如果没有找到k开始的子串,则返回回溯状态visited[i ] [j] = false,继续向后面访问。

分析一波复杂度:时间复杂度为O(ML*3^L),M,N 为网格的长度和宽度,L 为字符串word的长度,第一次电泳check函数的时候,回向4个方向进行测试,其余坐标的节点都是3个方向检车,走过的分支不会反方向回去,左移check函数的复杂度为3^L,而网格上面有MN个坐标,且存在剪枝,最坏的情况下是O(MN * 3 ^L).空间复杂符是O(MN) visited数组的空间是O(MN) ,check递归栈的最大深度在最坏的情况下是O(MN)

class Solution {public boolean exist(char[][] board, String word) {char[] words = word.toCharArray();for(int i = 0; i < board.length; i++){for(int j  = 0; j < board[i].length;j++){if(dfs(board,words,i,j,0)){return true;}}}return false;}public boolean dfs(char [][] board,char[] words,int i,int j, int k){// 边界+条件if(i >= board.length || i < 0 || j >= board[0].length || j < 0 || board[i][j] != words[k]){return false;}// 终止条件if(k ==  words.length - 1){return true;}// 防止重复board[i][j] = '\0';boolean res = dfs(board,words,i+1,j,k+1) || dfs(board,words,i - 1,j,k+1) || 							dfs(board,words,i,j - 1,k+1)  ||  dfs(board,words,i,j+ 1,k+1);// 恢复board[i][j] = words[k];return res;}
}

总结

提示:组合总和问题;分割问题;子集问题;排列问题;搜索问题


如果有帮助到你,请给题解点个赞和收藏,让更多的人看到 ~ ("▔□▔)/

如有不理解的地方,欢迎你在评论区给我留言,我都会逐一回复 ~

也欢迎你 关注我 ,喜欢交朋友,喜欢一起探讨问题。

在这里插入图片描述

http://www.15wanjia.com/news/49601.html

相关文章:

  • 深圳好点的网站建设公司百度手机助手下载苹果版
  • 信息技术制作网站地推一手项目平台
  • 哈尔滨企业建站服务商企业网站模板
  • 关于网站建设的入门书新闻发稿软文推广
  • 申请域名建立网站怎么申请建立网站
  • 畅言 wordpress插件深圳优化网站方法
  • 网站建设好销售吗seogw
  • 公司网站域名怎么取5118营销大数据
  • php网站的客服窗口怎么做的外贸怎么建立自己的网站
  • 网站运营方案模板网站建设在线建站
  • ubuntu 下载wordpress济南网络优化网站
  • 网站模板 html广东疫情最新数据
  • 襄阳市建设局网站seo搜索引擎优化期末考试
  • 荥阳网站建设公司网址收录
  • 设计参考网站推荐百度知道提问首页
  • 番禺知名网站建设公司遵义网站seo
  • 做seo网站推广价格又有什么新病毒出现了
  • 做网站有什么注意事项互联网平台
  • 市住房官方建设委网站2022最火营销方案
  • 东莞专业网站推广公司滕州百度推广
  • 政府网站集约化建设试点工作方案百度百科词条入口
  • 建设银行公积金网站提示udun磁力屋 最好用
  • 网站建设单位有哪些内容百度收录的网站多久更新一次
  • 移动端网站模板怎么做的广州网站优化服务
  • 网站策划ppt人民日报客户端
  • 阿里云香港节点做的网站大型网站建设平台
  • wordpress做线下交易西安网站建设优化
  • 哪个网站可以做私单百度seo排名培训优化
  • 宿迁做网站的公司我想注册一个网站怎么注册
  • 做网站的公司搞什么活动视频号怎么付费推广