leecode更新
This commit is contained in:
parent
f3e88db25c
commit
c1f0422617
|
|
@ -0,0 +1,88 @@
|
|||
package com.markilue.leecode.hashtable;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.hashtable
|
||||
*@Author: dingjiawen
|
||||
*@CreateTime: 2022-12-28 10:12
|
||||
*@Description:
|
||||
* TODO 力扣383题 赎金信:
|
||||
* 给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。
|
||||
* 如果可以,返回 true ;否则返回 false 。
|
||||
* magazine 中的每个字符只能在 ransomNote 中使用一次。
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T06_CanConstruct {
|
||||
|
||||
/**
|
||||
* 思路本质上还是和第一题同素异形类似,记录字母出现的次数,只不过允许多不允许少
|
||||
* 速度击败99.88%,内存击败76.12%
|
||||
* @param ransomNote
|
||||
* @param magazine
|
||||
* @return
|
||||
*/
|
||||
public boolean canConstruct(String ransomNote, String magazine) {
|
||||
char[] mChars = magazine.toCharArray();
|
||||
char[] rChars = ransomNote.toCharArray();
|
||||
|
||||
int[] map = new int[26];//数组当map用
|
||||
for (char mChar : mChars) {
|
||||
map[mChar-'a']++;
|
||||
}
|
||||
|
||||
for (char rChar : rChars) {
|
||||
map[rChar-'a']--;
|
||||
}
|
||||
|
||||
for (int i : map) {
|
||||
if(i<0){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 思路:浅优化,判断可以在第二个for就开始
|
||||
* 速度击败99.88%,内存击败71.7%
|
||||
* @param ransomNote
|
||||
* @param magazine
|
||||
* @return
|
||||
*/
|
||||
public boolean canConstruct2(String ransomNote, String magazine) {
|
||||
char[] mChars = magazine.toCharArray();
|
||||
char[] rChars = ransomNote.toCharArray();
|
||||
|
||||
int[] map = new int[26];//数组当map用
|
||||
for (char mChar : mChars) {
|
||||
map[mChar-'a']++;
|
||||
}
|
||||
|
||||
for (char rChar : rChars) {
|
||||
map[rChar-'a']--;
|
||||
if(map[rChar-'a']<0){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 官方最快:记录这次找到的位置,如果下次要找相同的字符只能从这次的后面开始找
|
||||
* 时间复杂度是不是要高一些,本质上取决于indexOf的时间复杂度
|
||||
* 速度击败100%,内存击败96.44%
|
||||
* @param ransomNote
|
||||
* @param magazine
|
||||
* @return
|
||||
*/
|
||||
public boolean canConstruct1(String ransomNote, String magazine) {
|
||||
int[] charIndex = new int[26];
|
||||
for (char c : ransomNote.toCharArray()) {
|
||||
int p = magazine.indexOf(c, charIndex[c - 'a']);//indexOf(char,fromIndex)
|
||||
if(p == -1) return false;
|
||||
charIndex[c - 'a'] = p + 1;//如果下次要找相同的字符只能从这次的后面开始找
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ import java.util.List;
|
|||
* 注意:答案中不可以包含重复的三元组。
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public class ThreeSum {
|
||||
public class T07_ThreeSum {
|
||||
|
||||
/**
|
||||
* 这道题使用哈希法的思路:
|
||||
|
|
@ -17,7 +17,7 @@ import java.util.*;
|
|||
* 你可以按 任意顺序 返回答案 。
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public class FourSum {
|
||||
public class T08_FourSum {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
package com.markilue.leecode.hashtable.second;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.hashtable.second
|
||||
*@Author: dingjiawen
|
||||
*@CreateTime: 2022-12-28 10:30
|
||||
*@Description:
|
||||
* TODO 二刷15题 三数之和:
|
||||
* 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,
|
||||
* 同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
|
||||
* 你返回所有和为 0 且不重复的三元组。
|
||||
* 注意:答案中不可以包含重复的三元组。
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T07_ThreeSum {
|
||||
|
||||
@Test
|
||||
public void test(){
|
||||
int[] nums = {-1, 0, 1, 2, -1, -4};
|
||||
System.out.println(threeSum(nums));
|
||||
}
|
||||
|
||||
/**
|
||||
* 思路:这题本质上是一个O(N^3)的一个暴力解法,考虑一层for放外面,里面用hashMap记录将复杂度变为O(N^2)
|
||||
* 由于对于结果不考虑index只考虑具体的数,因此考虑先对数组进行排序
|
||||
* 速度击败47.14%,内存击败84.92% 22ms
|
||||
* 增加第一个数大于0,则一定不可能了的判断以后 速度击败75.68%,内存击败80.11% 20ms
|
||||
* @param nums
|
||||
* @return
|
||||
*/
|
||||
public List<List<Integer>> threeSum(int[] nums) {
|
||||
List<List<Integer>> result = new ArrayList<>();
|
||||
if (nums.length < 3) {
|
||||
return result;
|
||||
}
|
||||
Arrays.sort(nums);//排序
|
||||
|
||||
for (int i = 0; i < nums.length - 2; i++) {
|
||||
//第一个数大于0,则一定不可能了
|
||||
if(nums[i]>0){
|
||||
break;
|
||||
}
|
||||
//避免重复
|
||||
if(i>0&&nums[i]==nums[i-1]){
|
||||
continue;
|
||||
}
|
||||
int left = i + 1;
|
||||
int right = nums.length - 1;
|
||||
while (left < right) {
|
||||
int sum = nums[left] + nums[right];
|
||||
if (sum > -nums[i]){
|
||||
//整体大于0
|
||||
right--;
|
||||
}else if(sum<-nums[i]){
|
||||
//整体小于0
|
||||
left++;
|
||||
}else {
|
||||
//刚刚好
|
||||
result.add(new ArrayList<>(Arrays.asList(nums[i],nums[left],nums[right])));
|
||||
left++;
|
||||
right--;
|
||||
//由于不能重复三元组,所以需要多偏移
|
||||
while (left<right&&nums[left-1]==nums[left])left++;
|
||||
while (left<right&&nums[right]==nums[right+1])right--;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 官方最快:9ms
|
||||
* 但是与本人几乎完全一致,所以经过测试是电脑原因
|
||||
* @param nums
|
||||
* @return
|
||||
*/
|
||||
public List<List<Integer>> threeSum1(int[] nums) {
|
||||
List<List<Integer>> res = new ArrayList<List<Integer>>();
|
||||
if(nums.length < 3) return res;
|
||||
Arrays.sort(nums);
|
||||
for(int i=0;i<nums.length-2;i++){
|
||||
if (i == 0 || (i > 0 && nums[i] != nums[i-1])) {
|
||||
int j = i+1;
|
||||
int k = nums.length-1;
|
||||
while(j<k){
|
||||
if(nums[i]+nums[j]+nums[k]==0){
|
||||
List<Integer> cur = new ArrayList<Integer>();
|
||||
cur.add(nums[i]);
|
||||
cur.add(nums[j]);
|
||||
cur.add(nums[k]);
|
||||
res.add(cur);
|
||||
while(j<k && nums[j]==nums[j+1])j++;
|
||||
while(j<k && nums[k]==nums[k-1])k--;
|
||||
j++;
|
||||
k--;
|
||||
}else if(nums[i]+nums[j]+nums[k] > 0) k--;
|
||||
else j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
package com.markilue.leecode.hashtable.second;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.hashtable.second
|
||||
*@Author: dingjiawen
|
||||
*@CreateTime: 2022-12-28 11:16
|
||||
*@Description:
|
||||
* TODO 二刷力扣18题 四数之和:
|
||||
* 给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。
|
||||
* 请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]]
|
||||
* (若两个四元组元素一一对应,则认为两个四元组重复):
|
||||
* 0 <= a, b, c, d < n
|
||||
* a、b、c 和 d 互不相同
|
||||
* nums[a] + nums[b] + nums[c] + nums[d] == target
|
||||
* 你可以按 任意顺序 返回答案 。
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T08_FourSum {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
int[] nums = {1, 0, -1, 0, -2, 2};
|
||||
int target = 0;
|
||||
System.out.println(fourSum(nums, target));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test1() {
|
||||
int[] nums = {2, 2, 2, 2, 2};
|
||||
int target = 8;
|
||||
System.out.println(fourSum(nums, target));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2() {
|
||||
int[] nums = {1, -2, -5, -4, -3, 3, 3, 5};
|
||||
int target = -11;
|
||||
System.out.println(fourSum(nums, target));
|
||||
}
|
||||
|
||||
/**
|
||||
* 思路:在三数之和外面再加上一层for,时间复杂度O(N^3)
|
||||
* 熟读击败49.87%,内存击败71.72%
|
||||
* @param nums
|
||||
* @param target
|
||||
* @return
|
||||
*/
|
||||
public List<List<Integer>> fourSum(int[] nums, int target) {
|
||||
List<List<Integer>> result = new ArrayList<>();
|
||||
if (nums.length < 4) {
|
||||
return result;
|
||||
}
|
||||
Arrays.sort(nums);
|
||||
|
||||
for (int i = 0; i < nums.length - 3; i++) {
|
||||
if (nums[i] > 0 && nums[i] > target) break;
|
||||
if (i > 0 && nums[i] == nums[i - 1]) continue;
|
||||
for (int j = i + 1; j < nums.length - 2; j++) {
|
||||
if (j > i + 1 && nums[j] == nums[j - 1]) continue;
|
||||
|
||||
int left = j + 1;
|
||||
int right = nums.length - 1;
|
||||
|
||||
while (left < right) {
|
||||
long sum = (long) target - nums[left] - nums[right];
|
||||
if (sum < nums[i] + nums[j]) {
|
||||
//整体大于target
|
||||
right--;
|
||||
} else if (sum > nums[i] + nums[j]) {
|
||||
//整体小于target
|
||||
left++;
|
||||
} else {
|
||||
//刚刚好
|
||||
result.add(new ArrayList<>(Arrays.asList(nums[i], nums[j], nums[left], nums[right])));
|
||||
left++;
|
||||
right--;
|
||||
while (left < right && nums[left - 1] == nums[left]) left++;
|
||||
while (left < right && nums[right + 1] == nums[right]) right--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 官方最快:2ms
|
||||
* 与本人一致,多了几个考验功力的减枝操作
|
||||
* @param nums
|
||||
* @param target
|
||||
* @return
|
||||
*/
|
||||
public List<List<Integer>> fourSum1(int[] nums, int target) {
|
||||
Arrays.sort(nums);
|
||||
List<List<Integer>> res = new ArrayList<>();
|
||||
int length = nums.length;
|
||||
for (int i = 0; i < length - 3; i++) {
|
||||
// 跳过重复值
|
||||
if (i > 0 && nums[i] == nums[i - 1]) {
|
||||
continue;
|
||||
}
|
||||
// 最小合都大于目标值,说明无解
|
||||
if ((long) nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) {
|
||||
//太大了
|
||||
break;
|
||||
}
|
||||
// 最大合小于目标值,说明i太小了,继续后移
|
||||
if ((long) nums[i] + nums[length - 3] + nums[length - 2] + nums[length - 1] < target) {
|
||||
//太小了
|
||||
continue;
|
||||
}
|
||||
for (int j = i + 1; j < length - 2; j++) {
|
||||
// 跳过重复的数字
|
||||
if (j > i + 1 && nums[j] == nums[j - 1]) {
|
||||
continue;
|
||||
}
|
||||
// 最小合都大于目标值,说明无解
|
||||
if ((long) nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) {
|
||||
break;
|
||||
}
|
||||
// 最大合小于目标值,说明i太小了,继续后移
|
||||
if ((long) nums[i] + nums[j] + nums[length - 2] + nums[length - 1] < target) {
|
||||
continue;
|
||||
}
|
||||
int left = j + 1, right = length - 1;
|
||||
while (left < right) {
|
||||
int x = nums[left], y = nums[right];
|
||||
int sum = nums[i] + nums[j] + x + y;
|
||||
if (sum == target) {
|
||||
res.add(Arrays.asList(nums[i], nums[j], x, y));
|
||||
// 将两个指针都往中间推移,遇到重复的数字就跳过
|
||||
left++;
|
||||
while (left < right && nums[left] == nums[left - 1]) {
|
||||
left++;
|
||||
}
|
||||
right--;
|
||||
while (left < right && nums[right] == nums[right + 1]) {
|
||||
right--;
|
||||
}
|
||||
} else if (sum < target) {
|
||||
// 和小于目标值,因为是排序过的,要想结果变大,左标就要往右移动,数字更大
|
||||
left++;
|
||||
} else {
|
||||
// 同理,和大于目标值,右标就要往左移动,数字更小
|
||||
right--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ import org.junit.Test;
|
|||
*
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public class ReverseString {
|
||||
public class T01_ReverseString {
|
||||
|
||||
@Test
|
||||
public void test(){
|
||||
|
|
@ -13,7 +13,7 @@ import org.junit.Test;
|
|||
* 2)如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public class ReverseStr {
|
||||
public class T02_ReverseStr {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package com.markilue.leecode.string;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.string
|
||||
*@Author: dingjiawen
|
||||
*@CreateTime: 2022-12-28 12:41
|
||||
*@Description:
|
||||
* TODO 剑指offer05 替换空格:
|
||||
*
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T03_ReplaceSpace {
|
||||
|
||||
@Test
|
||||
public void test(){
|
||||
String s = "We are happy.";
|
||||
System.out.println(replaceSpace(s));
|
||||
}
|
||||
|
||||
/**
|
||||
* 思路:使用额外的辅助空间build进行构造
|
||||
* 速度击败100%,内存击败36.8%
|
||||
* @param s
|
||||
* @return
|
||||
*/
|
||||
public String replaceSpace(String s) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
char[] chars = s.toCharArray();
|
||||
for (char aChar : chars) {
|
||||
if(' '==aChar){
|
||||
builder.append("%20");
|
||||
}else {
|
||||
builder.append(aChar);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 双指针法:不使用额外的空间,首先将原来的进行扩容
|
||||
* 速度击败100%,内存击败20.93%
|
||||
* @param s
|
||||
* @return
|
||||
*/
|
||||
public String replaceSpace1(String s) {
|
||||
int count = 0; // 统计空格的个数
|
||||
int sOldSize = s.length();
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
if (s.charAt(i) == ' ') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
// 扩充字符串s的大小,也就是每个空格替换成"%20"之后的大小
|
||||
char[] chars = Arrays.copyOf(s.toCharArray(), s.length() + count * 2);
|
||||
int sNewSize = chars.length;
|
||||
// 从后先前将空格替换为"%20"
|
||||
for (int i = sNewSize - 1, j = sOldSize - 1; j < i; i--, j--) {
|
||||
if (chars[j] != ' ') {
|
||||
chars[i] = chars[j];
|
||||
} else {
|
||||
chars[i] = '0';
|
||||
chars[i - 1] = '2';
|
||||
chars[i - 2] = '%';
|
||||
i -= 2;
|
||||
}
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
package com.markilue.leecode.string.second;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.string.second
|
||||
*@Author: dingjiawen
|
||||
*@CreateTime: 2022-12-28 12:00
|
||||
*@Description:
|
||||
* TODO 二刷力扣344题 反转字符串:
|
||||
* 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
|
||||
* 不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T01_ReverseString {
|
||||
|
||||
@Test
|
||||
public void test(){
|
||||
char[] s = {'h', 'e', 'l', 'l', 'o'};
|
||||
reverseString(s);
|
||||
System.out.println(Arrays.toString(s));
|
||||
}
|
||||
|
||||
/**
|
||||
* 思路:两头指针分别对换
|
||||
* 速度击败100%,内存击败15.55%
|
||||
* @param s
|
||||
*/
|
||||
public void reverseString(char[] s) {
|
||||
int left=0;
|
||||
int right=s.length-1;
|
||||
while (left<right){
|
||||
exchange(s,left,right);
|
||||
left++;
|
||||
right--;
|
||||
}
|
||||
}
|
||||
|
||||
public void exchange(char[] s,int left,int right){
|
||||
char temp=s[left];
|
||||
s[left]=s[right];
|
||||
s[right]=temp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* temp提出减少内存
|
||||
* @param s
|
||||
*/
|
||||
public void reverseString1(char[] s) {
|
||||
|
||||
if (s.length<=1) {
|
||||
return;
|
||||
}
|
||||
|
||||
char temp;
|
||||
for (int i = 0; i < s.length / 2; i++) {
|
||||
temp=s[i];
|
||||
s[i]=s[s.length-1-i];
|
||||
s[s.length-1-i]=temp;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 官方位运算交换
|
||||
* 速度击败100%,内存击败67.99%
|
||||
* @param s
|
||||
*/
|
||||
public void reverseString2(char[] s) {
|
||||
int l = 0;
|
||||
int r = s.length - 1;
|
||||
while (l < r) {
|
||||
s[l] ^= s[r]; //构造 a ^ b 的结果,并放在 a 中
|
||||
s[r] ^= s[l]; //将 a ^ b 这一结果再 ^ b ,存入b中,此时 b = a, a = a ^ b
|
||||
s[l] ^= s[r]; //a ^ b 的结果再 ^ a ,存入 a 中,此时 b = a, a = b 完成交换
|
||||
l++;
|
||||
r--;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package com.markilue.leecode.string.second;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.string.second
|
||||
*@Author: dingjiawen
|
||||
*@CreateTime: 2022-12-28 12:22
|
||||
*@Description:
|
||||
* TODO 二刷力扣541题 反转字符串 II
|
||||
* 给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。
|
||||
* 1)如果剩余字符少于 k 个,则将剩余字符全部反转。
|
||||
* 2)如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T02_ReverseStr {
|
||||
|
||||
@Test
|
||||
public void test(){
|
||||
String s = "abcdefg";
|
||||
int k = 2;
|
||||
System.out.println(reverseStr(s,k));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test1(){
|
||||
String s = "abcdef";
|
||||
int k = 2;
|
||||
System.out.println(reverseStr(s,k));
|
||||
}
|
||||
|
||||
/**
|
||||
* 速度击败100%,内存击败25.83%
|
||||
* @param s
|
||||
* @param k
|
||||
* @return
|
||||
*/
|
||||
public String reverseStr(String s, int k) {
|
||||
|
||||
char[] chars = s.toCharArray();
|
||||
for (int i = 0; i < chars.length; i+=2*k) {
|
||||
if(i+k> chars.length-1){
|
||||
reverse(chars,i, chars.length-1);
|
||||
}else {
|
||||
reverse(chars,i,i+k-1);
|
||||
}
|
||||
}
|
||||
return new String(chars);
|
||||
|
||||
}
|
||||
public void reverse(char[] s, int startIndex,int endIndex) {
|
||||
char temp;
|
||||
while (startIndex<endIndex){
|
||||
temp=s[startIndex];
|
||||
s[startIndex]=s[endIndex];
|
||||
s[endIndex]=temp;
|
||||
startIndex++;
|
||||
endIndex--;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue