*241. Different Ways to Add Parentheses
class Solution {
public List<Integer> diffWaysToCompute(String expression) {
return dfs(0, expression.length() - 1, expression.toCharArray());
}
public List<Integer> dfs(int start, int end, char[] expression) {
List<Integer> res = new ArrayList<>();
for (int i = start; i <= end; i++) {
if (Character.isDigit(expression[i])) {
continue;
}
int curr = 0;
List<Integer> leftRes = dfs(start, i - 1, expression);
List<Integer> rightRes = dfs(i + 1, end, expression);
for (int val : leftRes) {
for (int val2 : rightRes) {
res.add(calculation(val, val2, expression[i]));
}
}
}
if (res.isEmpty()) {
int curr = 0;
for (int i = start; i <= end; i++) {
curr = curr * 10 + expression[i] - '0';
}
res.add(curr);
}
return res;
}
public int calculation(int a, int b, char op) {
return
switch (op) {
case '+' -> a + b;
case '-' -> a - b;
case '*' -> a * b;
default -> -1;
};
}
}
257. Binary Tree Paths
Recursive
class Solution {
public List<String> ans=new ArrayList<>();
public List<String> binaryTreePaths(TreeNode root) {
bfs(root,"");
return ans;
}
public void bfs(TreeNode root, String s){
if (root.left==null&&root.right==null){
String resString=s+"->"+root.val;
ans.add(resString.substring(2));
return;
}
s=s+"->"+root.val;
if (root.left!=null){
bfs(root.left,s);
}
if (root.right!=null){
bfs(root.right,s);
}
}
}
*258. Add Digits
数学上提到:
- 能够被9整除的整数,各位上的数字加起来也必然能被9整除,所以,连续累加起来,最终必然就是9。
- 不能被9整除的整数,各位上的数字加起来,结果对9取模,和初始数对9取摸,是一样的,所以,连续累加起来,最终必然就是初始数对9取摸。
int addDigits(int num)
{
if(0 == num % 9)
{
return 9;
}
return num % 9;
}
上面的两句综合一下,就是楼主说的这一句:
return (num - 1) % 9 + 1;
263. Ugly Number
Recursive
public boolean isUgly(int n) {
if(n<=0){
return false;
}
return backTrack(n);
}
public boolean backTrack(int n){
if(n<=5){
return true;
}
return ((n%2==0)&&backTrack(n/2))||((n%3==0)&&backTrack(n/3))||((n%5==0)&&backTrack(n/5));
}
*268. Missing Number
XOR
public int missingNumber(int[] nums) {
int res=0;
for (int i=0;i<nums.length;i++) {
res=res^nums[i]^i;
}
res^=nums.length;
return res;
}
Sum
public int missingNumber(int[] nums) {
int res = 0;
for (int i = 0; i < nums.length; i++) {
res += i - nums[i];
}
res+=nums.length;
return res;
}
445. Add Two Numbers II
reverse链表
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode n1=reverse(l1);
ListNode n2 =reverse(l2);
int carrying=0;
ListNode curr1=n1;
ListNode curr2=n2;
ListNode curr=n1;
ListNode prev=null;
while (curr1!=null&&curr2!=null) {
int res = carrying + curr1.val + curr2.val;
curr1.val = res % 10;
curr2.val = res % 10;
carrying = res / 10;
prev=curr1;
curr1 = curr1.next;
curr2 = curr2.next;
}
while (curr1!=null){
int res = carrying + curr1.val;
curr1.val=res%10;
carrying=res/10;
prev=curr1;
curr1=curr1.next;
}
while (curr2!=null){
curr=n2;
int res=carrying+curr2.val;
curr2.val=res%10;
carrying=res/10;
prev=curr2;
curr2=curr2.next;
}
if (carrying!=0){
prev.next=new ListNode(1);
}
return reverse(curr);
}
public ListNode reverse(ListNode node){
ListNode curr=node;
ListNode prev=null;
while (curr!=null){
var next=curr.next;
curr.next=prev;
prev=curr;
curr=next;
}
return prev;
}
}
450. Delete Node in a BST
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
return bfs(root,key);
}
public TreeNode bfs(TreeNode root,int key){
if (root==null){
return null;
}
if (root.val>key){
root.left=bfs(root.left,key);
}
else if (root.val<key){
root.right=bfs(root.right,key);
}
else {
if(root.left==null){
return root.right;
}
else if(root.right==null){
return root.left;
}
var curr=root.right;
while (curr.left!=null){
curr=curr.left;
}
root.val=curr.val;
root.right = bfs(root.right,curr.val);
}
return root;
}
}
468. Validate IP Address(Solved)
纯恶心人的,规则匹配
class Solution {
public static final String V4="IPv4";
public static final String V6="IPv6";
public static final String ERR="Neither";
public String validIPAddress(String queryIP) {
//identify type
//v4
String[] resV4=queryIP.split("\\.",5);
String[] resV6=queryIP.split(":",9);
if(validateV4(resV4)){
return V4;
}
if(validateV6(resV6)){
return V6;
}
return ERR;
}
public boolean validateV4(String[] resV4){
if(resV4.length!=4){
return false;
}
for (String s : resV4) {
if (s.length()>4||s.length()<1) {
return false;
}
if(s.matches(".*\\D+.*")){
return false;
}
if(s.startsWith("0")&&s.length()!=1){
return false;
}
if(Integer.parseInt(s)>255){
return false;
}
}
return true;
}
public boolean validateV6(String[] resV6){
if(resV6.length!=8){
return false;
}
for (String s : resV6) {
if (s.length()>4||s.length()<1) {
return false;
}
if(s.matches(".*[^A-F|0-9|a-f]+.*")){
return false;
}
}
return true;
}
}
Target Sum
Back Track
int ways=0;
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
ways=0;
backTrack(nums,0,0,target);
return ways;
}
void backTrack(vector<int>& nums,int curr,int curr_sum, int target){
if (curr==nums.size()){
if (target==curr_sum){
ways++;
}
return ;
}
backTrack(nums,curr+1,curr_sum+nums[curr],target);
backTrack(nums,curr+1,curr_sum-nums[curr],target);
}
};
dp
/**
原问题等同于: 找到nums一个正子集P和一个负子集N,使得总和等于target。即sum(P) - sum(N) == target,
即sum(P) + sum(N) + sum(P) - sum(N) == target + sum(P) + sum(N)
即2 * sum(P) == target + sum(nums), 其中target + sum(nums)必须>=0且为偶数,否则等式不可能成立。
则问题转换为:存在多少个子集P,使sum(P) == (target + sum(nums))/2。
dp[i][j]表示前i个元素有多少个目标和为j的子集。dp[0][0] = 1
1. dp[i][j] = dp[i-1][j]
2. 如果nums[0...i-2]存在目标和为j-nums[i-1]的子集,则dp[i][j] += dp[i-1][j-nums[i-1]]
*/
class Solution {
public int findTargetSumWays(int[] nums, int target) {
int sum = 0;
for (int num: nums) sum += num;
if (target+sum<0 || ((target+sum)&1)==1) return 0; // 必须>=0且为偶数
int T = (target+sum)>>1;
int[] pre = new int[T+1];
pre[0] = 1;
for (int i=1; i<=nums.length; ++i){
int[] curr = new int[T+1];
for (int j=0; j<=T; ++j){
curr[j] = pre[j];
if (j-nums[i-1]>=0) curr[j] += pre[j-nums[i-1]];
}
pre = curr;
}
return pre[T];
}
}
498. Diagonal Traverse
public int[] findDiagonalOrder(int[][] matrix) {
if (matrix == null || matrix.length == 0) {
return new int[]{};
}
int r = 0, c = 0;
int row = matrix.length, col = matrix[0].length;
int[] res = new int[row * col];
for (int i = 0; i < res.length; i++) {
res[i] = matrix[r][c];
// r + c 即为遍历的层数,偶数向上遍历,奇数向下遍历
if ((r + c) % 2 == 0) {
if (c == col - 1) {
// 往下移动一格准备向下遍历
r++;
} else if (r == 0) {
// 往右移动一格准备向下遍历
c++;
} else {
// 往上移动
r--;
c++;
}
} else {
if (r == row - 1) {
// 往右移动一格准备向上遍历
c++;
} else if (c == 0) {
// 往下移动一格准备向上遍历
r++;
} else {
// 往下移动
r++;
c--;
}
}
}
return res;
}
Next Greater Element II
Monotonic Stack
根据上面的分析可知,可以遍历一次数组,如果元素是单调递减的(则他们的「下一个更大元素」相同),我们就把这些元素保存,直到找到一个较大的元素;把该较大元素逐一跟保存了的元素比较,如果该元素更大,那么它就是前面元素的「下一个更大元素」。
在实现上,我们可以使用「单调栈」来实现,单调栈是说栈里面的元素从栈底到栈顶是单调递增或者单调递减的(类似于汉诺塔)。
本题应该用个「单调递减栈」来实现。
建立「单调递减栈」,并对原数组遍历一次:
- 如果栈为空,则把当前元素放入栈内;
- 如果栈不为空,则需要判断当前元素和栈顶元素的大小:
- 如果当前元素比栈顶元素大:说明当前元素是前面一些元素的「下一个更大元素」,则逐个弹出栈顶元素,直到当前元素比栈顶元素小为止。
- 如果当前元素比栈顶元素小:说明当前元素的「下一个更大元素」与栈顶元素相同,则把当前元素入栈。
public int[] nextGreaterElements(int[] nums) {
Stack<Integer> monoStack=new Stack<>();
int[] res=new int[nums.length];
for (int i=0;i<nums.length;i++){
res[i]=-1;
}
for (int i=0;i<nums.length*2-1;i++){
if (monoStack.isEmpty()||nums[monoStack.peek()]>=nums[i% nums.length]){
monoStack.push(i% nums.length);
}
else{
while (!monoStack.isEmpty()&&nums[monoStack.peek()]<nums[i% nums.length]){
res[monoStack.pop()]=nums[i% nums.length];
}
monoStack.push(i% nums.length);
}
}
return res;
}
518. Coin Change II
使用带记忆的决策树,会超时
public class Solution {
public static int totals;
public static HashMap<Pair<Integer,Integer>,Integer> visited=new HashMap<>();
public static int coinTypes;
public static int[] values;
static class Pair<T,E>{
public T first;
public E second;
Pair(T t,E e){
this.first=t;
this.second=e;
}
}
public int change(int amount, int[] coins) {
totals=amount;
coinTypes=coins.length;
values=coins;
return bfs(0,0);
}
public int bfs(int i,int currAmount){
//当前金额等于总金额
if(currAmount==totals){
return 1;
}
//当前金额超过总金额
if(currAmount>totals){
return 0;
}
//当前使用的硬币种类超过了总种类(0...n-1)
if(i>=coinTypes){
return 0;
}
//这个方法已经访问过了
Pair<Integer,Integer>currValuePair=new Pair<Integer,Integer>(i,currAmount);
if(visited.containsKey(currValuePair)){
return visited.get(currValuePair);
}
//两种策略,继续使用当前种类硬币或者在以后都抛弃这种硬币
visited.put(currValuePair,bfs(i,currAmount+values[i])+bfs(i+1,currAmount));
return visited.get(currValuePair);
}
}
使用DP O ( m ∗ n ) O(m*n) O(m∗n)
public int change(int amount, int[] coins) {
int[][] dp=new int[amount+1][coins.length+1];
for(int i=0;i<=coins.length;i++){
dp[0][i]=1;
}
for(int i=1;i<=amount;i++){
for(int j=coins.length-1;j>=0;j--){
dp[i][j]=dp[i][j+1];
if(i-coins[j]>=0){
dp[i][j]+=dp[i-coins[j]][j];
}
}
}
return dp[amount][0];
}
DP优化 O ( n ) O(n) O(n)
public int change(int amount, int[] coins) {
int[] dp=new int[amount+1];
dp[0]=1;
for (int i=coins.length-1;i>=0;i--){
int[] nextDp=new int[amount+1];
nextDp[0]=1;
for(int j=1;j<=amount;j++){
nextDp[j]+=dp[j];
if(j>=coins[i]) {
nextDp[j] += nextDp[j - coins[i]];
}
}
dp=nextDp;
}
return dp[amount];
}
}
543. Diameter of Binary Tree
class Solution {
public static int maxBothLen=0;
public int diameterOfBinaryTree(TreeNode root) {
maxBothLen=0;
maxLength(root);
return maxBothLen;
}
public int maxLength(TreeNode root){
if(root==null){
return -1;
}
int leftHeight=maxLength(root.left);
int rightHeight=maxLength(root.right);
maxBothLen=Math.max(leftHeight+rightHeight+2,maxBothLen);
return Math.max(leftHeight,rightHeight)+1;
}
}
560. Subarray Sum Equals K
public int subarraySum(int[] nums, int k) {
int res=0;
int curr_sum=0;
for(int left=0;left<nums.length;left++){
curr_sum=0;
for(int right=left;right<nums.length;right++){
curr_sum+=nums[right];
if(curr_sum==k){
res++;
}
}
}
return res;
}
572. Subtree of Another Tree
class Solution {
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
if(subRoot==null){
return true;
}
if(root==null){
return false;
}
return sameTree(root,subRoot)||isSubtree(root.right,subRoot)||isSubtree(root.left, subRoot);
}
public boolean sameTree(TreeNode root,TreeNode subRoot){
if(root==null&&subRoot==null){
return true;
}
if(root == null || subRoot == null){
return false;
}
if(root.val!=subRoot.val){
return false;
}
return sameTree(root.left,subRoot.left)&&sameTree(root.right,subRoot.right);
}
}
647. Palindromic Substrings
class Solution {
public int countSubstrings(String s) {
int res=0;
for (int i=0;i<s.length();i++){
res+=computePalindrome(s,i,i);
res+=computePalindrome(s,i,i+1);
}
return res;
}
public int computePalindrome(String s,int left,int right){
int res=0;
while (left>=0&&right<s.length()&&s.charAt(left)==s.charAt(right)){
left--;
right++;
res++;
}
return res;
}
}
678. Valid Parenthesis String
贪心算法 非常精妙
public boolean checkValidString(String s) {
int leftMin=0;
int leftMax=0;
for (int i=0;i<s.length();i++){
char ch=s.charAt(i);
if (ch=='('){
leftMin++;
leftMax++;
}
else if (ch==')'){
leftMin--;
leftMax--;
}
else {
leftMin--;
leftMax++;
}
if (leftMax<0){
return false;
}
if (leftMin<0){
leftMin=0;
}
}
return leftMin==0;
}
695. Max Area of Island
class Solution {
public static int max_len;
public static int curr_len;
public int maxAreaOfIsland(int[][] grid) {
max_len=0;
for(int i=0;i<grid.length;i++){
for(int j=0;j<grid[0].length;j++){
if(grid[i][j]==1){
curr_len=0;
dfs(grid,i,j);
}
}
}
return max_len;
}
public void dfs(int[][] grid,int i,int j){
if(grid[i][j]==0){
return ;
}
grid[i][j]=0;
curr_len++;
max_len=Math.max(curr_len,max_len);
if(i>0){
dfs(grid,i-1,j);
}
if(i<grid.length-1){
dfs(grid,i+1,j);
}
if(j>0){
dfs(grid,i,j-1);
}
if(j<grid[0].length-1){
dfs(grid,i,j+1);
}
}
}
696. Count Binary Substrings
public int countBinarySubstrings(String s) {
int i=0;
int ans=0;
int cnt0=0,cnt1=0;
while(i<s.length()){
cnt0=0;
cnt1=0;
if(s.charAt(i)=='0'){
//count 0's
while (i<s.length()&&s.charAt(i)=='0'){
cnt0++;
i++;
}
int j=i;
//count 1's
while (j<s.length()&&s.charAt(j)=='1'){
cnt1++;
j++;
}
}
else{
while (i<s.length()&&s.charAt(i)=='1'){
cnt1++;
i++;
}
int j=i;
//count 1's
while (j<s.length()&&s.charAt(j)=='0'){
cnt0++;
j++;
}
}
ans+=Math.min(cnt1,cnt0);
}
return ans;
}
704. Binary Search
class Solution {
public int search(int[] nums, int target) {
return binarySearch(nums,0,nums.length-1,target);
}
public int binarySearch(int[] nums,int start,int end,int target){
if(start>end){
return -1;
}
int mid=(start+end)/2;
if(nums[mid]==target){
return mid;
}
else if(nums[mid]>target){
return binarySearch(nums,start,mid-1,target);
}
else{
return binarySearch(nums,mid+1,end,target);
}
}
}
718. Maximum Length of Repeated Subarray
public int findLength(int[] nums1, int[] nums2) {
int row=nums1.length+1;
int column=nums2.length+1;
int maxLen=0;
int[][] maxMatrix=new int[row][column];
for(int i=1;i<row;i++){
for(int j=1;j<column;j++){
if(nums1[i-1]==nums2[j-1]){
maxMatrix[i][j]=maxMatrix[i-1][j-1]+1;
maxLen=Math.max(maxMatrix[i][j],maxLen);
}
else{
maxMatrix[i][j]=0;
}
}
}
return maxLen;
}
739. Daily Temperatures
单调栈
public int[] dailyTemperatures(int[] temperatures) {
Deque<Integer> tempIdxs=new ArrayDeque<>();
int[] res=new int[temperatures.length];
for(int i=0;i<temperatures.length;i++){
while(!tempIdxs.isEmpty()&&temperatures[tempIdxs.peekLast()]<temperatures[i]){
int curr_idx = tempIdxs.removeLast();
res[curr_idx] =(i-curr_idx);
}
tempIdxs.addLast(i);
}
return res;
}
853. Car Fleet
public int carFleet(int target, int[] pos, int[] speed) {
int N = pos.length, res = 0;
double[][] cars = new double[N][2];
for (int i = 0; i < N; ++i)
cars[i] = new double[] {pos[i], (double)(target - pos[i]) / speed[i]};
Arrays.sort(cars, (a, b) -> Double.compare(a[0], b[0]));
double cur = 0;
for (int i = N - 1; i >= 0 ; --i) {
if (cars[i][1] > cur) {
cur = cars[i][1];
res++;
}
}
return res;
}
887. Super Egg Drop
使用dp[Move][Eggs]方程
public int superEggDrop(int E, int F) {
int[][] floors = new int[F+1][E+1];
for (int d=1; d<=F; d++) {
for (int e=1; e<=E; e++) {
floors[d][e] = 1
+ floors[d-1][e-1]
+ floors[d-1][e];
if (floors[d][e] >= F) {
return d;
}
}
}
return -1;
}
912. Sort an Array
快排,仅使用三数取中,未极限优化
class Solution {
public int[] sortArray(int[] nums) {
quickSort(nums,0,nums.length-1);
return nums;
}
public void quickSort(int[] nums,int left,int right){
if (left<right){
int pivot = partition(nums,left,right);
quickSort(nums,left,pivot-1);
quickSort(nums,pivot+1,right);
}
}
public int threeMiden(int[] nums,int a,int b,int c){
if (nums[a] >= nums[b] && nums[a] <= nums[c] || nums[a] <= nums[b] && nums[a] >= nums[c]) {
return a;
} else if (nums[b] >= nums[a] && nums[b] <= nums[c] || nums[b] <= nums[a] && nums[b] >=nums[c]) {
return b;
} else {
return c;
}
}
public int partition(int[] nums,int left,int right){
int tmp;
int median=threeMiden(nums,left,right,left+1);
tmp = nums[left];
nums[left]=nums[median];
nums[median]=tmp;
int pivot=nums[left];
int i=left;
int j=right;
while (i<j) {
while (i<j&&nums[j]>=pivot){
j--;
}
while(i<j&&nums[i]<=pivot){
i++;
}
tmp=nums[i];
nums[i]=nums[j];
nums[j]=tmp;
}
tmp=nums[left];
nums[left]=nums[j];
nums[j]=tmp;
return i;
}
}
958. Check Completeness of a Binary Tree(Solved)
广度优先遍历
public boolean isCompleteTree(TreeNode root) {
Queue<TreeNode> totals=new LinkedList<>();
Queue<TreeNode> currLevel=new LinkedList<>();
boolean tag=false;
totals.add(root);
while (!totals.isEmpty()){
while (!totals.isEmpty()){
TreeNode node=totals.poll();
//左没有右有的情形
System.out.println(node.val);
if(node.left==null&&node.right!=null){
return false;
}
//跳跃叶子情形
if((node.left==null||node.right==null)&& !tag){
tag=true;
}
else if(tag&&(node.left!=null||node.right!=null)){
return false;
}
if(node.left!=null){
currLevel.add(node.left);
}
if(node.right!=null) {
currLevel.add(node.right);
}
}
totals.addAll(currLevel);
currLevel.clear();
}
return true;
}
优化后
public boolean isCompleteTree(TreeNode root) {
Queue<TreeNode> totals=new LinkedList<>();
totals.add(root);
TreeNode node=null;
while (!totals.isEmpty()){
node=totals.poll();
if(node!=null){
totals.add(node.left);
totals.add(node.right);
}
else{
while (!totals.isEmpty()){
node=totals.poll();
if(node!=null){
return false;
}
}
}
}
return true;
}
1004. Max Consecutive Ones III
滑窗
class Solution {
public:
int longestOnes(vector<int>& nums, int k) {
if (nums.empty()){
return 0;
}
int left=0;
int right=0;
int maxLen=0;
while (right<nums.size()){
if (nums[right]==0){
k--;
if (k<0){
maxLen=max(maxLen,right-left);
while (nums[left]==1){
left++;
}
left++;
}
}
right++;
}
maxLen= max(right-left,maxLen);
return maxLen;
}
};
1047. Remove All Adjacent Duplicates In String
public String removeDuplicates(String s) {
Stack<Character> characterStack = new Stack<>();
for (int i = 0; i < s.length(); i++) {
if (characterStack.isEmpty()) {
characterStack.push(s.charAt(i));
}
else{
if (characterStack.peek()==s.charAt(i)){
characterStack.pop();
}
else{
characterStack.push(s.charAt(i));
}
}
}
StringBuilder builder=new StringBuilder();
Iterator<Character> iterator=characterStack.iterator();
for (var e:characterStack){
builder.append(e);
}
return builder.toString();
}
1143. Longest Common Subsequence
public int longestCommonSubsequence(String text1, String text2) {
int[][] maxLCS=new int[text1.length()+1][text2.length()+1];
int max_len=0;
for(int i=1;i<=text1.length();i++){
for(int j=1;j<=text2.length();j++){
if(text1.charAt(i-1)==text2.charAt(j-1)){
maxLCS[i][j]=maxLCS[i-1][j-1]+1;
max_len=Math.max(maxLCS[i][j],max_len);
}
else{
maxLCS[i][j]=Math.max(Math.max(maxLCS[i-1][j-1],maxLCS[i][j-1]),maxLCS[i-1][j]);
}
}
}
return max_len;
}
1504. Count Submatrices With All Ones
矩阵压缩 Source
public int numSubmat(int[][] mat) {
int row = mat.length;
int column = mat[0].length;
int res = 0;
for (int i = 0; i < mat.length; i++) {
for (int j = i; j < row; j++) {
int cur = 0;
for (int k = 0; k < column; k++) {
if (mat[j][k] == 0) {
cur = 0;
continue;
}
if (k == 0) {
cur = 1;
}
else{
cur++;
}
res+=cur;
}
}
for (int j=row-1;j>i;j--){
for (int k=0;k<column;k++){
mat[j][k]=mat[j][k]&mat[j-1][k];
}
}
}
return res;
}