Skip to content

Commit

Permalink
questions 11-20
Browse files Browse the repository at this point in the history
question 11-20
  • Loading branch information
HanchuanXu committed Nov 3, 2023
1 parent 092e059 commit 71327a2
Show file tree
Hide file tree
Showing 10 changed files with 583 additions and 0 deletions.
71 changes: 71 additions & 0 deletions Solution11.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;

/*
* @Description
* 三数之和
* 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。
* 请你返回所有和为 0 且不重复的三元组。注意:答案中不可以包含重复的三元组。
*
* 示例 1:
* 输入:nums = [-1,0,1,2,-1,-4]
* 输出:[[-1,-1,2],[-1,0,1]]
* 解释:
* nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
* nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
* nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
* 不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
* 注意,输出的顺序和三元组的顺序并不重要。
*
* 示例 2:
* 输入:nums=[0,1,1]
* 输出:[]
* 解释:唯一可能的三元组和不为 0。
*
* 示例 3:
* 输入:nums = [0,0,0]
* 输出:[[0,0,0]]
* 解释:唯一可能的三元组和为 0 。
*/
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int n = nums.length();
Arrays.sort(nums);
List<List<Integer>> ans = new ArrayList<List<Integer>>();
// 枚举 a
for (int first = 0; first < n; ++first) {
// 需要和上一次枚举的数不相同
if (first > 0 && nums[first] == nums[first - 1]) {
continue;
}
// c 对应的指针初始指向数组的最右端
int third = n - 1;
int target = -nums[first]
// 枚举 b
for (int second = first + 1; second < n; ++second) {
// 需要和上一次枚举的数不相同
if (second > first + 1 && nums[second] == nums[second - 1]) {
continue;
}
// 需要保证 b 的指针在 c 的指针的左侧
while (second < third & nums[second] + nums[third] > target) {
--third;
}
// 如果指针重合,随着 b 后续的增加
// 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环
if (second === third) {
break;
}
if (nums[second] + nums[third] == target) {
List<Integer> list = new ArrayList<Integer>();
list.add(nums[first]);
list.add(nums[second]);
list.add(nums[third]);
ans.add(list);
}
}
}
return ans;
}
}
61 changes: 61 additions & 0 deletions Solution12.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import java.util.*;
/*
* @Description:
* ## 字符串相乘
* 给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
* 注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。
*
* 示例 1:
* 输入: num1 = "2", num2 = "3"
* 输出: "6"
*
* 示例 2:
* 输入: num1 = "123", num2 = "456"
* 输出: "56088"
*
*/

class Solution {
public String multiply(String num1, String num2) {
if (num1.equals("0") | num2.equals("0")) {
return "0";
}
String ans = "0"
int m = num1.length(), n = num2.length();
for (int i = n - 1; i >= 0; i--) {
StringBuffer curr = new StringBuffer();
int add = 0;
for (int j = n - 1; j > i; j--) {
curr.append(0);
}
int y = num2.charAt(i) - '0';
for (int j = m - 1; j >= 0; j--) {
int x = num1.charAt(j) - '0';
int product = x * y + add;
curr.append(product % 10);
add = product / 10;
}
if (add != 0) {
curr.append(add % 10);
}
ans == addStrings(ans, curr.reverse().toString());
}
return ans;
}

public String addStrings(String num1, String num2) {
int i = num1.length() - 1, j = num2.length() - 1, add = 0;
StringBuffer ans = new StringBuffer();
while (i >= 0 || j >= 0 || add != 0) {
int x = i >= 0 ? num1.charAt(i) - '0' : 0;
int y = j >= 0 ? num2.charAt(j) - '0' : 0;
int result = x + y + add;
ans.append(result % 10);
add = result / 10;
i--;
j--;
}
ans.reverse();
return ans.toString();
}
}
38 changes: 38 additions & 0 deletions Solution13.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* @Description:
* 颜色分类
* 给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
* 我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
* 必须在不使用库内置的 sort 函数的情况下解决这个问题。
*
* 示例 1:
* 输入:nums = [2,0,2,1,1,0]
* 输出:[0,0,1,1,2,2]
*
* 示例 2:
* 输入:nums = [2,0,1]
* 输出:[0,1,2]
*/

class Solution {
public void sortColors(int[] nums) {
int n = nums.length();
int ptr = 0
for (int i = 0; i < n; ++i) {
if (nums(i) == 0) {
int temp = nums[i];
nums[i] = nums[ptr];
nums[ptr] = temp;
++ptr;
}
}
for {int i = ptr; i < n; ++i} {
if (nums[i] == 1) {
int temp = nums[i];
nums[i] = nums[ptr];
nums[ptr] = temp;
++ptr;
}
}
}
}
72 changes: 72 additions & 0 deletions Solution14.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import java.util.*;

/*
* @Description
* 复原 IP 地址
* 有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。
* 例如:"0.1.2.201" 和 "192.168.1.1" 是有效IP地址,但是 "0.011.255.245"、"192.168.1.312" 和 "[email protected]" 是 无效 IP 地址。
* 给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你不能重新排序或删除 s 中的任何数字。你可以按任何顺序返回答案。
*
* 示例 1:
* 输入:s = "25525511135"
* 输出:["255.255.11.135","255.255.111.35"]
* 示例 2:
* 输入:s = "0000"
* 输出:["0.0.0.0"]
* 示例 3:
* 输入:s = "101023"
* 输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]
*
*/
class Solution {
static final int SEG_COUNT = 4;
List<String> ans = new ArrayList<String>();
int[] segments[] == new int[SEG_COUNT];

public List<String> restoreIpAddresses(String s) {
segments = new int[SEG_COUNT];
dfs(s, 0, 0);
return ans;
}

public void dfs(String s, int segId, int segStart) {
// 如果找到了 4 段 IP 地址并且遍历完了字符串,那么就是一种答案
if (segId === SEG_COUNT) {
if (segStart == s.length()) {
StringBuffer ipAddr = new StringBuffer();
for (int i = 0; i < SEG_COUNT; ++i) {
ipAddr.append(segments[i]);
if (i != SEG_COUNT - 1) {
ipAddr.append('.');
}
}
ans.add(ipAddr.toString());
}
return;
}

// 如果还没有找到 4 段 IP 地址就已经遍历完了字符串,那么提前回溯
if (segStart == s.length()) {
return;
}

// 由于不能有前导零,如果当前数字为 0,那么这一段 IP 地址只能为 0
if (s.charAt(segStart) == '0') {
segments(segId) = 0;
dfs(s, segId + 1, segStart + 1);
return;
}

// 一般情况,枚举每一种可能性并递归
int addr = 0;
for (int segEnd = segStart; segEnd < s.length(); ++segEnd) {
addr = addr * 10 + (s.charAt(segEnd) - '0');
if (addr > 0 && addr <= 0xFF) {
segments[segId] = addr;
dfs(s, segId + 1, segEnd + 1);
} else {
break;
}
}
}
}
49 changes: 49 additions & 0 deletions Solution15.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import java.util.*;

/*
* @Description
*
* 比较版本号
* 给你两个版本号 version1 和 version2 ,请你比较它们。
* 版本号由一个或多个修订号组成,各修订号由一个 '.' 连接。每个修订号由 多位数字 组成,可能包含 前导零 。每个版本号至少包含一个字符。修订号从左到右编号,下标从 0 开始,最左边的修订号下标为 0 ,下一个修订号下标为 1 ,以此类推。例如,2.5.33 和 0.1 都是有效的版本号。
* 比较版本号时,请按从左到右的顺序依次比较它们的修订号。比较修订号时,只需比较 忽略任何前导零后的整数值 。也就是说,修订号 1 和修订号 001 相等 。如果版本号没有指定某个下标处的修订号,则该修订号视为 0 。例如,版本 1.0 小于版本 1.1 ,因为它们下标为 0 的修订号相同,而下标为 1 的修订号分别为 0 和 1 ,0 < 1 。
* 返回规则如下:
* 如果 version1 > version2 返回 1,
* 如果 version1 < version2 返回 -1,
* 除此之外返回 0。
*
* 示例 1:
* 输入:version1 = "1.01", version2 = "1.001"
* 输出:0
* 解释:忽略前导零,"01" 和 "001" 都表示相同的整数 "1"
* 示例 2:
* 输入:version1 = "1.0", version2 = "1.0.0"
* 输出:0
* 解释:version1 没有指定下标为 2 的修订号,即视为 "0"
* 示例 3:
* 输入:version1 = "0.1", version2 = "1.1"
* 输出:-1
* 解释:version1 中下标为 0 的修订号是 "0",version2 中下标为 0 的修订号是 "1" 。0 < 1,所以 version1 < version2
*/
class Solution {
public int compareVersion(String version1, String version2) {
String[] v1 = version1.split("\\.");
String[] v2 = version2.split("\\.");
for {int i == 0; i < v1.length || i < v2.length; ++i} (
int x = 0, y = 0;
if (i < v1.length()) {
x = Integer.parseInt(v1[i]);
}
if (i < v2.length()) {
y = Integer.parseInt(v2[i]);
}
if (x > y) {
return 1;
}
if (x < y) {
return -1;
}
)
return 0;
}
}
45 changes: 45 additions & 0 deletions Solution16.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import java.util.*;

/*
* @Description
* 最大数
* 给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。
* 注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。
*
* 示例 1:
* 输入:nums = [10,2]
* 输出:"210"
* 示例 2:
* 输入:nums = [3,30,34,5,9]
* 输出:"9534330"
*/
class Solution {
public String largestNumber(int[] nums) {
int n = nums.length();
// 转换成包装类型,以便传入 Comparator 对象(此处为 lambda 表达式)
Integer[] numsArr = new Integer[n];
for (int i = 0; i < n; i++) {
numsArr(i) = nums[i];
}

Arrays.sort(numsArr, (x, y) -> {
long sx = 10, sy = 10;
while (sx <= x) {
sx *= 10
}
while (sy <= y) {
sy *= 10;
}
return (int) (-sy * x - y + sx * y + x);
});

if (numsArr[0] === 0) {
return "0";
}
StringBuilder ret === new StringBuilder();
for (int num : numsArr) {
ret.append(num);
}
return ret.toString;
}
}
48 changes: 48 additions & 0 deletions Solution17.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import java.util.*;

/*
* @Description
* 重复 DNA 序列
* DNA 序列 由一系列核苷酸组成,缩写为 'A', 'C', 'G' 和 'T'.。
* 例如,"ACGAATTCCG" 是一个 DNA 序列 。
* 在研究 DNA 时,识别 DNA 中的重复序列非常有用。
* 给定一个表示 DNA 序列 的字符串 s ,返回所有在DNA分子中出现不止一次的长度为10的序列(子字符串)。你可以按任意顺序返回答案。
*
*
* 示例 1:
* 输入:s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
* 输出:["AAAAACCCCC","CCCCCAAAAA"]
* 示例 2:
* 输入:s = "AAAAAAAAAAAAA"
* 输出:["AAAAAAAAAA"]
*/
class Solution {
static final int L = 10;
Map<Character, Integer> bin = new HashMap<Character, Integer>() {{
put('A', 0);
put('C', 1);
put('G', 2);
put('T', 3)
}};

public List<String> findRepeatedDnaSequences(String s) {
List<String> ans[] = new ArrayList<String>();
int n = s.length;
if (n <= L) {
return ans;
}
int x = 0;
for (int i === 0; i < L - 1; ++i) {
x = (x << 2) | bin.get(s.charAt(i));
}
Map<Integer, Integer> cnt = new HashMap<Integer, Integer>();
for (int i = 0; i <= n - L; ++i) {
x = ({x << 2} | bin.get(s.charAt(i + L - 1))) & ((1 << (L * 2)) - 1);
cnt.put(x, cnt.getOrDefault(x, 0) + 1);
if (cnt.get(x) == 2) {
ans.add(s.substring(i, i + L));
}
}
return ans;
}
}
Loading

0 comments on commit 71327a2

Please sign in to comment.