leecode更新
This commit is contained in:
parent
e948057876
commit
c9c55164b7
|
|
@ -17,7 +17,7 @@ import java.util.List;
|
||||||
* 对于给定的输入,保证和为 target 的不同组合数少于 150 个。
|
* 对于给定的输入,保证和为 target 的不同组合数少于 150 个。
|
||||||
* @Version: 1.0
|
* @Version: 1.0
|
||||||
*/
|
*/
|
||||||
public class combinationSum {
|
public class T04_CombinationSum {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
|
|
@ -15,7 +15,7 @@ import java.util.*;
|
||||||
* 注意:解集不能包含重复的组合。
|
* 注意:解集不能包含重复的组合。
|
||||||
* @Version: 1.0
|
* @Version: 1.0
|
||||||
*/
|
*/
|
||||||
public class combinationSum2 {
|
public class T05_CombinationSum2 {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test(){
|
public void test(){
|
||||||
|
|
@ -15,7 +15,7 @@ import java.util.List;
|
||||||
* 回文串 是正着读和反着读都一样的字符串。
|
* 回文串 是正着读和反着读都一样的字符串。
|
||||||
* @Version: 1.0
|
* @Version: 1.0
|
||||||
*/
|
*/
|
||||||
public class partition {
|
public class T06_Partition {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
|
|
@ -17,7 +17,7 @@ import java.util.List;
|
||||||
* 给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。
|
* 给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。
|
||||||
* @Version: 1.0
|
* @Version: 1.0
|
||||||
*/
|
*/
|
||||||
public class RestoreIpAddresses {
|
public class T07_RestoreIpAddresses {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test1() {
|
public void test1() {
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
package com.markilue.leecode.backtrace.second;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.backtrace.second
|
||||||
|
*@Author: dingjiawen
|
||||||
|
*@CreateTime: 2023-02-01 09:53
|
||||||
|
*@Description:
|
||||||
|
* TODO 二刷力扣39题 组合总和:
|
||||||
|
* 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
|
||||||
|
* candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
|
||||||
|
* 对于给定的输入,保证和为 target 的不同组合数少于 150 个。
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T04_CombinationSum {
|
||||||
|
|
||||||
|
|
||||||
|
List<List<Integer>> result = new ArrayList<>();
|
||||||
|
List<Integer> cur = new ArrayList<>();
|
||||||
|
|
||||||
|
public List<List<Integer>> combinationSum(int[] candidates, int target) {
|
||||||
|
Arrays.sort(candidates);
|
||||||
|
backtracking(candidates,target,0,0);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void backtracking(int[] candidates, int target, int sum,int now) {
|
||||||
|
if (sum == target) {
|
||||||
|
result.add(new ArrayList<>(cur));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = now; i < candidates.length; i++) {
|
||||||
|
if (sum + candidates[i] > target) {//剪枝
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cur.add(candidates[i]);
|
||||||
|
backtracking(candidates, target, sum + candidates[i],i);
|
||||||
|
cur.remove(cur.size()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 官方最快,form记录一个数最多能用多少次,小于0就不能用了
|
||||||
|
* @param con
|
||||||
|
* @param target
|
||||||
|
* @param form
|
||||||
|
* @param cur
|
||||||
|
* @param sum
|
||||||
|
* @param start
|
||||||
|
*/
|
||||||
|
private void deal(List<List<Integer>> con,int target,int[] form,List<Integer> cur,int sum,int start){
|
||||||
|
//dfs
|
||||||
|
if(sum==target) {
|
||||||
|
con.add(new ArrayList<Integer>(cur));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(int i=start;i<=target-sum;++i){
|
||||||
|
if(form[i]>0){
|
||||||
|
cur.add(i);
|
||||||
|
--form[i];
|
||||||
|
sum+=i;
|
||||||
|
deal(con,target,form,cur,sum,i);
|
||||||
|
sum-=i;
|
||||||
|
++form[i];
|
||||||
|
cur.remove(cur.size()-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
|
||||||
|
int[] form=new int[51];
|
||||||
|
for(int i=0;i<candidates.length;++i){
|
||||||
|
++form[candidates[i]];
|
||||||
|
}
|
||||||
|
List<List<Integer>> con=new ArrayList<List<Integer>>();
|
||||||
|
deal(con,target,form,new ArrayList<Integer>(),0,1);
|
||||||
|
return con;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.markilue.leecode.backtrace.second;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.backtrace.second
|
||||||
|
*@Author: dingjiawen
|
||||||
|
*@CreateTime: 2023-02-01 10:22
|
||||||
|
*@Description:
|
||||||
|
* TODO 二刷力扣40题 组合总和II:
|
||||||
|
* 给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
|
||||||
|
* candidates 中的每个数字在每个组合中只能使用 一次 。
|
||||||
|
* 注意:解集不能包含重复的组合。
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T05_CombinationSum2 {
|
||||||
|
|
||||||
|
List<Integer> cur=new ArrayList<>();
|
||||||
|
List<List<Integer>> result=new ArrayList<>();
|
||||||
|
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
|
||||||
|
Arrays.sort(candidates);
|
||||||
|
backtracking(candidates,target,0,0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void backtracking(int[] candidates, int target,int sum ,int startIndex) {
|
||||||
|
if(target==sum){
|
||||||
|
result.add(new ArrayList<>(cur));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = startIndex; i < candidates.length; i++) {
|
||||||
|
if(sum+candidates[i]>target){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(i!=startIndex&&candidates[i]==candidates[i-1])continue;
|
||||||
|
cur.add(candidates[i]);
|
||||||
|
backtracking(candidates,target,sum+candidates[i],i+1);
|
||||||
|
cur.remove(cur.size()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,155 @@
|
||||||
|
package com.markilue.leecode.backtrace.second;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.backtrace.second
|
||||||
|
*@Author: dingjiawen
|
||||||
|
*@CreateTime: 2023-02-01 11:01
|
||||||
|
*@Description:
|
||||||
|
* TODO 二刷力扣131题 分割回文串:
|
||||||
|
* 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。
|
||||||
|
* 回文串 是正着读和反着读都一样的字符串。
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T06_Partition {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
String s = "abbab";
|
||||||
|
|
||||||
|
System.out.println(partition(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
List<List<String>> result = new ArrayList<>();
|
||||||
|
List<String> cur = new ArrayList<>();
|
||||||
|
boolean[][] flag;
|
||||||
|
|
||||||
|
public List<List<String>> partition(String s) {
|
||||||
|
flag = new boolean[s.length()][s.length()];
|
||||||
|
computePalindrome1(s);
|
||||||
|
backtracking(s.toCharArray(), 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用动态规划前:速度击败73.84%,内存击败55.32% 7ms
|
||||||
|
* 使用动态规划后:速度击败99.22%,内存击败47.98% 6ms
|
||||||
|
* @param chars
|
||||||
|
* @param start
|
||||||
|
*/
|
||||||
|
public void backtracking(char[] chars, int start) {
|
||||||
|
if (start == chars.length) {
|
||||||
|
//分完了,直接加入
|
||||||
|
result.add(new ArrayList<>(cur));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for (int i = start; i < chars.length; i++) {
|
||||||
|
builder.append(chars[i]);
|
||||||
|
if (flag[start][i]) {
|
||||||
|
cur.add(builder.toString());
|
||||||
|
backtracking(chars, i + 1);
|
||||||
|
cur.remove(cur.size() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPalindrome(char[] chars, int start, int end) {
|
||||||
|
if (start == end) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
while (start < end) {
|
||||||
|
if (chars[start++] != chars[end--]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 事实上判断回文不需要一个一个进行判断,可以通过动态规划递归进行判断
|
||||||
|
* TODO 动态规划五部曲:
|
||||||
|
* 1)dp定义:dp[i][j]表示start为i,end为j的字符串是否是回文
|
||||||
|
* 2)dp状态转移方程:dp[i][j]可以通过dp[i+1][j-1]来推断
|
||||||
|
* dp[i][j]=char[i]==char[j]&&dp[i+1][j-1]
|
||||||
|
* 3)dp遍历顺序:由于需要知道i+1,j-1所以需要从下到上,左到右
|
||||||
|
* 4)dp初始化:dp[i][i]=true;dp[i][i>j]=true
|
||||||
|
* 5)dp距离推导: s="aab"
|
||||||
|
* [a a b]
|
||||||
|
* i=0: t t f
|
||||||
|
* i=1: t t f
|
||||||
|
* i=2: t t t
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param s
|
||||||
|
*/
|
||||||
|
public void computePalindrome(String s) {
|
||||||
|
char[] chars = s.toCharArray();
|
||||||
|
//初始化,下三角全为true
|
||||||
|
for (int i = 0; i < s.length(); i++) {
|
||||||
|
for (int j = 0; j <= i; j++) {
|
||||||
|
flag[i][j] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = s.length() - 2; i >= 0; i--) {
|
||||||
|
for (int j = s.length() - 1; j > i; j--) {
|
||||||
|
flag[i][j] = chars[i] == chars[j] && flag[i + 1][j - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据官方的优化
|
||||||
|
* @param s
|
||||||
|
*/
|
||||||
|
public void computePalindrome1(String s) {
|
||||||
|
char[] chars = s.toCharArray();
|
||||||
|
// //初始化,下三角全为true
|
||||||
|
// for (int i = 0; i < s.length(); i++) {
|
||||||
|
// for (int j = 0; j <= i; j++) {
|
||||||
|
// flag[i][j] = true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
for (int i = s.length() - 1; i >= 0; i--) {
|
||||||
|
for (int j = i; j <s.length(); j++) {
|
||||||
|
if(i==j) flag[i][j]=true;
|
||||||
|
else if(j==i+1) flag[i][j]=chars[i]==chars[j];//相差1的时候只需要判断这两个数是否相等
|
||||||
|
else flag[i][j] = chars[i] == chars[j] && flag[i + 1][j - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据一维dp优化
|
||||||
|
* @param s
|
||||||
|
*/
|
||||||
|
public void computePalindrome2(String s) {
|
||||||
|
char[] chars = s.toCharArray();
|
||||||
|
// //初始化,下三角全为true
|
||||||
|
// for (int i = 0; i < s.length(); i++) {
|
||||||
|
// for (int j = 0; j <= i; j++) {
|
||||||
|
// flag[i][j] = true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
for (int i = s.length() - 1; i >= 0; i--) {
|
||||||
|
for (int j = i; j <s.length(); j++) {
|
||||||
|
if(i==j) flag[i][j]=true;
|
||||||
|
else if(j==i+1) flag[i][j]=chars[i]==chars[j];//相差1的时候只需要判断这两个数是否相等
|
||||||
|
else flag[i][j] = chars[i] == chars[j] && flag[i + 1][j - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
package com.markilue.leecode.backtrace.second;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@BelongsProject: Leecode
|
||||||
|
*@BelongsPackage: com.markilue.leecode.backtrace.second
|
||||||
|
*@Author: dingjiawen
|
||||||
|
*@CreateTime: 2023-02-01 12:36
|
||||||
|
*@Description:
|
||||||
|
* TODO 二刷力扣93题 复原IP地址:
|
||||||
|
* 有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。
|
||||||
|
* 例如:"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址,但是 "0.011.255.245"、"192.168.1.312" 和 "192.168@1.1" 是 无效 IP 地址。
|
||||||
|
* 给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。
|
||||||
|
*@Version: 1.0
|
||||||
|
*/
|
||||||
|
public class T07_RestoreIpAddresses {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
String s = "25525511135";
|
||||||
|
String s1 = "0000";
|
||||||
|
System.out.println(restoreIpAddresses(s1));
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本质上类似于切割回文T06,核心在于最后一层一定要切完
|
||||||
|
* @param s
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<String> restoreIpAddresses(String s) {
|
||||||
|
backtracking(s, 0, 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void backtracking(String s, int level, int start) {
|
||||||
|
if (level == 4) {
|
||||||
|
builder.deleteCharAt(builder.length() - 1);
|
||||||
|
result.add(builder.toString());
|
||||||
|
builder.append(".");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int flag = start + 3 > s.length() ? s.length() : start + 3;
|
||||||
|
for (int i = start; i < flag; i++) {
|
||||||
|
String now;
|
||||||
|
if (level == 3) {
|
||||||
|
now = s.substring(i);
|
||||||
|
if (!isFit(now)) return;
|
||||||
|
} else {
|
||||||
|
now = s.substring(start, i + 1);
|
||||||
|
}
|
||||||
|
if (isFit(now)) {
|
||||||
|
builder.append(now).append(".");
|
||||||
|
backtracking(s, level + 1, i + 1);
|
||||||
|
int last = builder.length();
|
||||||
|
builder.delete(last - now.length() - 1, last);
|
||||||
|
}
|
||||||
|
if (level == 3) {
|
||||||
|
//最后一层就一次
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFit(String s) {
|
||||||
|
if (s.length() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (s.length() > 1 && s.charAt(0) == '0') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
long num = Long.parseLong(s);
|
||||||
|
|
||||||
|
return num >= 0 && num <= 255;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 官方最快0ms
|
||||||
|
* 使用segment记录pasInt的数,最后在拼接,避免了一系列删除增加“.”的操作
|
||||||
|
*/
|
||||||
|
List<String> res = new ArrayList<>();
|
||||||
|
int[] segment = new int[4];
|
||||||
|
public List<String> restoreIpAddresses1(String s) {
|
||||||
|
dfs(s,0,0);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
public void dfs(String s,int segnum,int p){
|
||||||
|
if(segnum == 4){
|
||||||
|
if(p == s.length()){
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for(int i = 0;i < 4;i++){
|
||||||
|
sb.append(segment[i]);
|
||||||
|
if(i != 3){
|
||||||
|
sb.append('.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.add(sb.toString());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(p == s.length()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(s.charAt(p) == '0'){
|
||||||
|
segment[segnum] = 0;
|
||||||
|
dfs(s,segnum+1,p+1);
|
||||||
|
}
|
||||||
|
int sum = 0;
|
||||||
|
for(int i = p;i < s.length();i++){
|
||||||
|
sum = sum * 10 + s.charAt(i) - '0';
|
||||||
|
if(sum > 0 && sum <= 255){
|
||||||
|
segment[segnum] = sum;
|
||||||
|
dfs(s,segnum+1,i+1);
|
||||||
|
}else{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue