From a72cff447c679eb399e1e023cee2bbfe96e06a09 Mon Sep 17 00:00:00 2001 From: fanxb Date: Thu, 10 Mar 2022 17:23:59 +0800 Subject: [PATCH] add --- 算法/leetcode/常规题/Q131 分割回文串.md | 4 +- 算法/leetcode/常规题/Q216.组合总和 3.md | 68 ++++++++++++++++++ 算法/leetcode/常规题/Q39.组合总和.md | 69 +++++++++++++++++++ 算法/leetcode/常规题/Q40.组合总和 2.md | 68 ++++++++++++++++++ .../leetcode/常规题/xml/q131-字符串切割.drawio | 1 + 算法/leetcode/常规题/xml/q39.drawio | 1 + .../leetcode/面试题/xml/q131-字符串切割.drawio | 1 - 7 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 算法/leetcode/常规题/Q216.组合总和 3.md create mode 100644 算法/leetcode/常规题/Q39.组合总和.md create mode 100644 算法/leetcode/常规题/Q40.组合总和 2.md create mode 100644 算法/leetcode/常规题/xml/q131-字符串切割.drawio create mode 100644 算法/leetcode/常规题/xml/q39.drawio delete mode 100644 算法/leetcode/面试题/xml/q131-字符串切割.drawio diff --git a/算法/leetcode/常规题/Q131 分割回文串.md b/算法/leetcode/常规题/Q131 分割回文串.md index 10be163..858ac2c 100644 --- a/算法/leetcode/常规题/Q131 分割回文串.md +++ b/算法/leetcode/常规题/Q131 分割回文串.md @@ -2,7 +2,7 @@ id: "20220309" date: "2022/03/09 20:15" title: "Q131 分割回文串(palindrome partitioning)" -tags: ["java", "leetcode", "dp", "dfs"] +tags: ["java", "leetcode", "dp", "dfs","回溯"] index_img: https://qiniupic.fleyx.com/blog/202203091650691.jpg?imageView2/2/w/200 banner_img: https://qiniupic.fleyx.com/blog/202203091650691.jpg categories: @@ -20,7 +20,7 @@ leetcode 中等难度,题目描述[点击这里](https://leetcode-cn.com/probl 判断回文数的方法很简单,两个指针从两端往中间遍历即可,或者先用 dp 计算得到所有的回文数组合(本解答采用 dp),本题字符串最长为 16,暴力判断和 dp 区别不大。 -关键是如何穷举出所有分割可能,简单的 for 循环显然是做不到的.具体分割方法可以先看下图: +关键是如何穷举出所有分割可能,简单的 for 循环显然是做不到的.需要用到回溯思想,具体分割方法可以先看下图: ## 字符串分割 diff --git a/算法/leetcode/常规题/Q216.组合总和 3.md b/算法/leetcode/常规题/Q216.组合总和 3.md new file mode 100644 index 0000000..18ad2e7 --- /dev/null +++ b/算法/leetcode/常规题/Q216.组合总和 3.md @@ -0,0 +1,68 @@ +--- +id: "202203103" +date: "2022/03/10 22:15" +title: "Q216 组合总和3(combination-sumⅢ)" +tags: ["java", "leetcode", "dfs"] +index_img: https://qiniupic.fleyx.com/blog/202203101631050.jpg?imageView2/2/w/200 +banner_img: https://qiniupic.fleyx.com/blog/202203101631050.jpg +categories: + - "算法" + - "leetcode刷题" +--- + + + +## 解析思路 + +leetcode 中等难度,题目描述[点击这里](https://leetcode-cn.com/problems/combination-sum-iii/)。 + +本题属于[组合排序 2](https://blog.fleyx.com/blog/detail/202203102/)的进阶题型。建议先看[上一篇](https://blog.fleyx.com/blog/detail/202203102/)的解析。 + +本题跟上一题区别只有一点是**选择的数字不能重复**,**同时对选择的数量有限制**如何实现呢? + +很简单,只需要 + +- 将传入的 index 设置成 index+1,实现不重复 +- ~~同时 for 循环时每次都循环到下一个不同的元素上~~由于本来提供的数字就不重复,因此可以去掉这一条 +- 循环和返回结果是都判断下元素数量 + +代码如下: + +## 代码 + +```java +public class Q216 { + public List> combinationSum3(int k, int n) { + int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + List> res = new ArrayList<>(); + dfs(arr, n, k, 0, new Stack<>(), res); + return res; + } + + private void dfs(int[] candidates, int n, int k, int index, Stack temp, List> res) { + if (n == 0) { + //说明找到一个结果序列 + if (temp.size() == k) { + //只有刚好k个数才是结果 + res.add(new ArrayList<>(temp)); + } + return; + } + for (int i = index; i < candidates.length; i++) { + if (candidates[i] > n || temp.size() == k) { + //前面已经排序过,所以在这里可以进行剪枝操作,如果candidates[index]都小于target了,那就不需要比较后面的了,肯定不满足要求 + //另外只能使用k个数,所以当temp的size为k时说明不能在装了,本条路结束 + return; + } + temp.push(candidates[i]); + dfs(candidates, n - candidates[i], k, i + 1, temp, res); + temp.pop(); + } + } + + public static void main(String[] args) { + new Q216().combinationSum3(3, 9).forEach(System.out::println); + } + +} +``` diff --git a/算法/leetcode/常规题/Q39.组合总和.md b/算法/leetcode/常规题/Q39.组合总和.md new file mode 100644 index 0000000..2ec0942 --- /dev/null +++ b/算法/leetcode/常规题/Q39.组合总和.md @@ -0,0 +1,69 @@ +--- +id: "202203101" +date: "2022/03/10 20:15" +title: "Q39 组合总和(combination-sum)" +tags: ["java", "leetcode", "dfs"] +index_img: https://qiniupic.fleyx.com/blog/202203101631050.jpg?imageView2/2/w/200 +banner_img: https://qiniupic.fleyx.com/blog/202203101631050.jpg +categories: + - "算法" + - "leetcode刷题" +--- + + + +## 解析思路 + +leetcode 中等难度,题目描述[点击这里](https://leetcode-cn.com/problems/combination-sum/)。 + +标准的回溯类题目,对于回溯类题目,通常都是要穷举所有的情况,然后判断那些情况是符合题目要求的。 + +然后穷举通常是通过`深度优先搜索(dfs)`来实现的,我们可以先将结果展开成一棵树,然后再根据这棵树来写代码,就比较好理解,如下图: + +以[2,3,5],8 为例: + +![展开](https://qiniupic.fleyx.com/blog/202203101700108.png) + +上图只对最左边的路径进行了完全展开(全部展开太麻烦了) + +总的来说回溯就是不断的进行尝试,如果尝试到最后发现不满足要求那就换一个路径继续尝试,属于暴力算法。因此此类题目的数据规模通常会限制的比较小。 + +另外通常还能根据题目的要求来做剪枝操作,减少一些不必要的运算。 + +比如本题可以先将数组排序,当选择的某个数已经大于目标值时,就没必须选择这个数的下一个数继续尝试了。 + +## 代码 + +```java +public class Q39 { + public List> combinationSum(int[] candidates, int target) { + List> res = new ArrayList<>(); + //排序 + Arrays.sort(candidates); + dfs(candidates, target, 0, new Stack<>(), res); + return res; + } + + private void dfs(int[] candidates, int target, int index, Stack temp, List> res) { + if (target == 0) { + //说明找到一个结果序列 + res.add(new ArrayList<>(temp)); + return; + } + for (int i = index; i < candidates.length; i++) { + if (candidates[i] > target) { + //前面已经排序过,所以在这里可以进行剪枝操作,如果candidates[index]都小于target了,那就不需要比较后面的了,肯定不满足要求 + return; + } + temp.push(candidates[i]); + //注意这里,为了让结果集不重复,选择重复元素时只能对当前元素进行重复选择,不能重复选择之前的元素。所以递归的index为i,不是0 + dfs(candidates, target - candidates[i], i, temp, res); + temp.pop(); + } + } + + public static void main(String[] args) { + new Q39().combinationSum(new int[]{2, 3, 5}, 8).forEach(System.out::println); + } +} +``` diff --git a/算法/leetcode/常规题/Q40.组合总和 2.md b/算法/leetcode/常规题/Q40.组合总和 2.md new file mode 100644 index 0000000..ac16a70 --- /dev/null +++ b/算法/leetcode/常规题/Q40.组合总和 2.md @@ -0,0 +1,68 @@ +--- +id: "202203102" +date: "2022/03/10 21:15" +title: "Q40 组合总和2(combination-sumⅡ)" +tags: ["java", "leetcode", "dfs"] +index_img: https://qiniupic.fleyx.com/blog/202203101631050.jpg?imageView2/2/w/200 +banner_img: https://qiniupic.fleyx.com/blog/202203101631050.jpg +categories: + - "算法" + - "leetcode刷题" +--- + + + +## 解析思路 + +leetcode 中等难度,题目描述[点击这里](https://leetcode-cn.com/problems/combination-sum-ii/)。 + +本题属于[组合排序](https://blog.fleyx.com/blog/detail/202203101/)的进阶题型。建议先看[上一篇](https://blog.fleyx.com/blog/detail/202203101/)的解析。 + +本题跟上一题区别只有一点是**选择的数字不能重复**,如何实现不重复呢? + +很简单,只需要将传入的 index 设置成 index+1,同时 for 循环时每次都循环到下一个不同的元素上 + +这样就不会选取到已经选过的元素。 + +代码如下: + +## 代码 + +```java +public class Q40 { + public List> combinationSum2(int[] candidates, int target) { + List> res = new ArrayList<>(); + Arrays.sort(candidates); + dfs(candidates, target, 0, new Stack<>(), res); + return res; + } + + private void dfs(int[] candidates, int target, int index, Stack temp, List> res) { + if (target == 0) { + //说明找到一个结果序列 + res.add(new ArrayList<>(temp)); + return; + } + for (int i = index; i < candidates.length; ) { + if (candidates[i] > target) { + //前面已经排序过,所以在这里可以进行剪枝操作,如果candidates[index]都小于target了,那就不需要比较后面的了,肯定不满足要求 + return; + } + temp.push(candidates[i]); + dfs(candidates, target - candidates[i], i + 1, temp, res); + temp.pop(); + //手动控制i的增长,对于同一个数字不能重复处理 + int nextI = i + 1; + while (nextI < candidates.length && candidates[nextI] == candidates[i]) { + nextI++; + } + i = nextI; + } + } + + public static void main(String[] args) { + new Q40().combinationSum2(new int[]{10, 1, 2, 7, 6, 1, 5}, 8).forEach(System.out::println); + } + +} +``` diff --git a/算法/leetcode/常规题/xml/q131-字符串切割.drawio b/算法/leetcode/常规题/xml/q131-字符串切割.drawio new file mode 100644 index 0000000..9560f59 --- /dev/null +++ b/算法/leetcode/常规题/xml/q131-字符串切割.drawio @@ -0,0 +1 @@ +7Vtdc6M2FP01ekwHJEDwCJhsd6Z96KYz3e0bsWWbFiMX49jur68kJAOWErwTG7N1ZvKBrmRA917OObrCAMWr/acyXS9/pTOSA2jN9gBNAIS2AyHgP9bsUFsCjGvDosxmclBjeMr+JdJoSes2m5FNZ2BFaV5l665xSouCTKuOLS1LuusOm9O8e9V1uiCa4Wma5rr1j2xWLWurD3Fj/5lki6W6su0Fdc8qVYPlTDbLdEZ3LRNKAIpLSqv6aLWPSc6dp/xSf+7xld7jjZWkqM75wPxLFP3mfHlZLT8nXyf+n9/w7vODI2/uJc23csYg8UAQA98CCQZRBHwfJC7/62N14MmuAInBCR+fPIIoBkEoJ1sdlAdLui1mhN+EBVC0W2YVeVqnU967YznDbMtqlbOWzQ7ntKhkEth8eJpni4I1cjJnk4z0OUs3vJCyIvuWSfrgE6ErUpUHNkT2+vgnt/6MzEjHkj7YNfF1MFSjlq3oenJkKpNqcTx743d2IF3/HWHwerxGy2pJF7RI818oXUtf/UWq6iCdlW4r2vUk81B5+Mo/z2Yim9/k6URjsu+0DrLVjgB6y+Ubui2n5I1Jqcc1LRekemMcqseRWedJ1ANYkjytspfug3nxUGAtFPzGnmSzoAX7F707OsN72RmVl/1BvPzjPAPuqKKjQLUhhRTgOH1+H7ZfALwh7mK3q0O3HVg6cKNrATfU6RN6OaeqJZuJt6hJq7bwrOq4z/tnS1XHw0bkG6NPy0brfdN5PAuOOeuGjHVr+g1B9AgSH4Q2CH3R5XAjI2Q/AaELEtZkXB0Jip4Iy5HGMSdq3+GWcAKYx+rBERQHET8DvxwbHwB/0hnvsx8kbsABocUtUS0W2Kkwv5ycLXNnPeGuE5i57ZmTfGJpUHWTZlOV9G8S05yWDTDMszw/MW1Y2mXFghncpvW7wIkH+FpyUpZ581yIsmU2m5FCA50L5KzjW52cPSZjO2kdQ9IG10paW3++Bye9N53bC6voTFhVq4iR4Coy4OrNIRV10/OYiq30xENCKrI1n4xVG7wviZ1z9fG4ktjRk/j2WYyc/iz2hsxi1+Cl2+snB6FeN7negG4KXtVPZ6sly6iWDMqGCZeYyxd2wOxhlMqahR+r0aLSEcRCTwkd1JFR9UEgpBYWskgvi3hcHNXXYM3IfVUN9QofVfmYsmgTJnQiHuVsmuah7FgxxZILKCTMG+mzOBVPozXNikoEyo2AO+HnYui3kZj1HZrq7GXQ+Qloo66ADwxayMQ28GpaSIezH0wLKY3TL4bGVWix9aLX/5Pnzw/QyKoAem2YlwF0FuvhrYuvqKB1WsOFhhqubRtruNdDEkMtoGEIsSr3g7RFLIKGmJWt4dlKviYfRi9hwIRCw0yi0B5idTBRwyO59q/ZS+ehAAmKYlebcEr74QjnQrliI9xVPNjWM8UfknEguhfcO3eVrih3LLh3zjJ9aMw77isqxMMG5T6ocDKscEZADc3G3WgcZVjjaLzQKrEGfAkR+g2Y3yt0q7XBca3qaoEcdKkAdT10pGxFtB+B7A+kSawNG0hD/fvjiTwjkH4/Bw0byOBOpJRSSP1SCo9KSqn7bj1pz3xn8dYy4VRNIXhjkQANZagPbjkHkqzeQA4LSbosNlUBIH+boqkAuCDCokZdv3H32FnSh4lY5IvdfR7puqL8XDa17mOxgC37sdiV90CEQOCaygdaseBeUwee7BkZi9G2IXmu9zYJNsDl6LDy1gsq6H9g5UWw8tbyDTl3It8UYPRv9Y9ri0bdd598G363v7/8PygkIV3ntshYw6Z7BSDnJG72rakE6aXe27+koWX3zb3kGbK7VqqOErG+rQtTIXPZr+7Se0l4GzudUDq2XsM0vfp5vZfrdIWphxK+Esr7jSPE/sjiaNLAp3FEhjje9/OIXGtkcTRtDp3G0THF8X6D6EB3qCCyZvMFTdHX+porSv4D \ No newline at end of file diff --git a/算法/leetcode/常规题/xml/q39.drawio b/算法/leetcode/常规题/xml/q39.drawio new file mode 100644 index 0000000..3f067bc --- /dev/null +++ b/算法/leetcode/常规题/xml/q39.drawio @@ -0,0 +1 @@ +7Vvtk6I2GP9r8tEdkhBePoLitZ3ttJ2dTu8+shKFOzQO4qr31zdIEGMQvXaXsOzN7OyQhyQkv+f9SQR4vNx/ysJ1/DuLaAqQEe0BngCELNvm/wvCoSSYFikJiyyJShKsCU/JdyqIhqBuk4hupI45Y2merGXijK1WdJZLtDDL2E7uNmep/NV1uKAK4WkWpir1nyTK45LqILum/0KTRVx9GVpu+WYZVp3FTjZxGLHdGQkHAI8zxvLyabkf07TArsKlHDe98va0sIyu8nsGxL/u/56mf5E/9vDb42eMXua/JSPBjE1+qDacse0qosUYA2CfZXnMFmwVpo+MrTkRcuJXmucHwapwmzNOivNlKt7y5WSHz8X4B1I1v4jpjo3JXmodRKtcCY0UftQbFKQN22Yz2rKrSlDCbEHzln7oxAYuvpQtKV8PH5fRNMyTF3kdoRCkxalfjTV/EHD/APRCTl7CdCu+hBRmFGg8hs9cpSSIwzRZrPjzjCNDM054oVmecKH1xItlEkXFHH5GN8n38Pk4XwHymiWr/LgT4gMyOcFeTED3TRolBtdyfM6Q6zKloipmHxkP2HTE5u9GWkz3Z7H8s7kQLocI4wJteQY2n2+4AFxy6rSo/848u5FVT6K5Yqsj+B9IlbBOVXIUVcLDUCX7pirZhimrwOsoFpQmdbpSq8rr/9Srqp+pU68gVBRLDRjepWJBoxlXMb3xAB2CXlOxOtCdpnhizA3hmAB77NwI9HZxktOndXgU2h0P5WVuXuWAIvtXMcWGIQOKRXtXx9XEKknxWUhd8fT1pdv8KMYG3WlsoFYvDkmTBA/C2lyx4idrU220x9alm4hXh9BbWoV+sLErbA9eudBD25I8wqj3Pha5Q9WCMsbXpQVVKDC8QLOUmPYUzparGP9XDap4S5q0sxQONTnxUxhqKVztOgxF5kXC7GoOQ9GHCUPxvbZIaxiKBhuGolthKNcF3HcXjFvty63zDA1prm77YrYCpgabnQNGrH4BBlUXBgIb+B7wLBAQ4AXA9UDgAN8G3rSg+AFwTBCYwHeKboELHAM4Lggs4PjAc4vhfEjRhwCH/+HjhCbwDBBMgT8GDl+qlfKd+c8Zf1oUT8dR0+Nw/okJ8FAxoQeBY4lveZOzj5bLID/29Uvmczbmb2fSCq+0KR1UMfUmz9g3OmYpy2pHN0/S9IL0CkIG4YVWVlb+TMggMVQpw28lZfjjHCHd6/ex1mI3VjPxgfh9fDMTN2wkq0fvo4BuEvF3pT1Xzt270R5TzeAHUsfC7Rk8T+AxllPKKgfur/qYzZatx3Ws+9VAaznXVNOTgRSySpFpcyKKGvTei8D2ZFItzHSdG0EiQ4qI7tzIakVMfzaJLgJ97YihdhmD2hHDZt8QawzEe4QYsqx+IWaqd0nfm3+vfMftC1FaD6qIGub+RPptkFbL8AOJpMitu2fIJb0PnYhqhgeagN+vL1ozj+q64vDKV6TdGxe3p1yn9/rSXA0ZhJ+4Ul7sSO7V862BFJ7IlWPwuvD0/i5Q4fbTSNVidR3bE1dCFCPNoT1uvI3Qo2QIVtd2e4NYe4li1APIbNgvyMx2yNRj4s4Rk0sU2NENmN13GbsoUehHrL2oM9JfOYRVvPz2kPFm/bvv0rXWP57Hwb8= \ No newline at end of file diff --git a/算法/leetcode/面试题/xml/q131-字符串切割.drawio b/算法/leetcode/面试题/xml/q131-字符串切割.drawio deleted file mode 100644 index ca2becd..0000000 --- a/算法/leetcode/面试题/xml/q131-字符串切割.drawio +++ /dev/null @@ -1 +0,0 @@ -7Vvfk6o2FP5r8rgdQoDAIyjb3pn2oXc703v7xmpUWjQW8ar963sSAoiJF++sgjvuzP4gJxHIOR/n+3KCiIyW+5/zZL34jU9ZhmxrukdkjGzbxwT+CsOhNLiuXxrmeTotTbgxvKT/MWW0lHWbTtmmNbDgPCvSdds44asVmxQtW5LnfNceNuNZ+6rrZM40w8skyXTrn+m0WKhp2bSx/8LS+aK6MvaCsmeZVIPVTDaLZMp3RyYSIzLKOS/Ko+V+xDLhu8ov5eeez/TWN5azVXHJB2afo+h35/O35eJT/GXs//WV7j49OermviXZVs0YxR4KRsi3UExRFCHfR7Er/vq0OvBUV0Dk4FiMj59RNEJBqCZbHCoP5ny7mjJxExYi0W6RFuxlnUxE7w4gA7ZFscygheFwxleFAgEWw5Msna+gkbEZTDJSN8vygu3PugHXzgVQMr5kRX6AIRUi6U9u+RmFSMdSPtg18XWoXY1aHEXXUyMTBap5ffbG73CgXP8DYfA6vMbzYsHnfJVkv3K+Vr76mxXFQTkr2Ra87UlwR374Ij4PM1HNr+p0sjHet1oH1TqOAKldzqbaY3LicLh7vs0n7DuzrJ7fJJ+z4jvjiDmAOcuSIv3Wvo+rh4JqoRBzf1HNFV/Bv+jN0bkDLztDetnvxcvv+Blwh4wO1kghQXSUvL4tt18hedu0nbtdPXXjwNITN7lV4rZ1+rS9TFDVAmbizUvSKi0CVS33ef9uedXxtJF4A/q0MFnvm876LHQkWDcE1i3pN0TRM4p9FGIU+rLLEUYgZD9GoYtiaAJXR5Kix9JS0zgVRO07whKOEXisHBzZ8iASZxCXg/EB8set8T78EHkDDgotYYlKsQCnouJyarbgznLCbSeA+dgzJ3gCZBRt0GyKnP/DRjzjeZMYZmmWnZg2ALt0NQeD27T+kHniyT4HTg5gnGVSlC3S6ZSttKRzBcw6vtXCbA3GY9A6BtAGtwIt1p/v3knPum5aJRemVWyZY9VPXiWGvDp4SiVteNZQPIIn7TOlEqz55F61wZVB7FyqjwcFsaODeHgUE6cbxV6fKHYNXhpePzmEdLrJ9Xp0U3BWP12sliyjWjIoGxAuIyFf4ADsYZSomoU/qkbLSkcwknpK6qCWjCoPAim1qJRFelnEE+KovAY0I/esGuoUPlXlYwKhZSB0IhH4dJJkoepYgmLJZCpk4I3kVZ5KwGjN01UhA+VGyB2Lc0H226ic9QOayrwMehMAMWkL+MCghUxsY99MC+np7L1roap02i2GBi20YL3o9SA8f3mAhq0C6LVhUQbQWayDt66+orKt0xqubajhYmys4d4ukxhqAQ1DyFW5HyRHxCJpCKywhoeVfEk+QC9hAEKhYSZZaA9pdTCuhkdq7V+yl85DAZEUBVcbC0p7d4RzJaxgQtuKh2IdKX6fjGOTh817l67SSw4eLO9dskzvO+fV+4pVxqMG5d6rcDKscO6AGpqNu7txlGGNo/HCUYk1EEuI0G+S+aOm7mptUK9VXS2QvS4VbF0P1ZRdEe1HILsDaRJr/QbSUP/+eCIvCKTfzUH9BjJ4VClVVSm6pRQdUkpVt3n0pL2KncWhZcKpmiL2wCLBNpShPrjlkpRkdQay35Sky2JTFcAWb1M0FQAXRVTWqMs37p5bS/owlot8ubsvIl1WlF/zptZdFwtg2U/lrryHIoIC11Q+0IoFjwod+2TPyFiMxgbw3O5tEmpIl3eXK4deUNn+R668Sq4cWr4R51HlW5VBurf6B92iqW6zS771v9vfXf7vNSURXecekbGWmx41ATknccNDUwnRS73Dv6ShoXtwL3kGdJdK1alErI91YSplLvzqLn0UwGPqtELpYL2GaXr183Yv1+kKUw+lfSaUjxtHm/p3FkeTBj6NIzHE8bGfR+JadxZH0+bQaRwdUxwfN4iO7fYVRGg2X9CUfUffciXx/w== \ No newline at end of file