leecode更新

This commit is contained in:
markilue 2023-02-01 13:29:43 +08:00
parent e948057876
commit c9c55164b7
8 changed files with 421 additions and 4 deletions

View File

@ -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() {

View File

@ -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(){

View File

@ -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() {

View File

@ -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() {

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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+1j-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];
}
}
}
}

View File

@ -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;
}
}
}
}