算法题【面试准备】

算法题【面试准备】

前言

2023-2-9 16:34:07

补充:
2023-7-16 17:55:56

公开发布于
2024-5-20 12:50:15

以下内容源自算法题
仅供学习交流使用

推荐

牛客

LeetCode

算法题

NC72二叉树的镜像

2023-2-9 16:40:26

NC72二叉树的镜像

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 *   public TreeNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param pRoot TreeNode类 
     * @return TreeNode类
     */
    public TreeNode Mirror (TreeNode pRoot) {
        // write code here
        if(pRoot==null){
            return null;
        }
        TreeNode temp=pRoot.left;
        pRoot.left=pRoot.right;
        pRoot.right=temp;
        Mirror(pRoot.left);
        Mirror(pRoot.right);
        return pRoot;
    }
}

剑指 Offer 27. 二叉树的镜像

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode mirrorTree(TreeNode root) {
        if(root==null){
            return null;
        }
        TreeNode tmp=root.left;
        root.left=root.right;
        root.right=tmp;
        mirrorTree(root.left);
        mirrorTree(root.right);
        return root;
    }
}

2023-2-9 16:45:40

NC8:二叉树根节点到叶子节点和为指定值的路径

2023-2-9 16:48:54

二叉树根节点到叶子节点和为指定值的路径

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */

public class Solution {
    /**
     * 
     * @param root TreeNode类 
     * @param sum int整型 
     * @return int整型ArrayList<ArrayList<>>
     */

    ArrayList<ArrayList<Integer>> res=new ArrayList<>();
    ArrayList<Integer> tmp=new ArrayList<>();
    public ArrayList<ArrayList<Integer>> pathSum (TreeNode root, int sum) {
        // write code here
        dfs(root,sum,0);
        return res;
    }

    void dfs(TreeNode root, int sum,int s){
        if(root==null){
            return;
        }
        tmp.add(root.val);
        s+=root.val;    
        if(root.left==null&&root.right==null){
            if(s==sum){
                res.add(new ArrayList<>(tmp));
            }
        }else{
            dfs(root.left,sum,s);
            dfs(root.right,sum,s);
        }
        tmp.remove(tmp.size()-1);
    }
}

剑指 Offer 34. 二叉树中和为某一值的路径

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    List<List<Integer>> res=new ArrayList<>();
    List<Integer> tmp=new ArrayList<Integer>();
    public List<List<Integer>> pathSum(TreeNode root, int target) {
        dfs(root,target,0);
        return res;
    }
    void dfs(TreeNode root, int target,int sum){
        if(root==null){
            return;
        }
        tmp.add(root.val);
        sum+=root.val;
        if(root.left==null&&root.right==null){
            if(sum==target){
                res.add(new ArrayList<>(tmp));
            }
        }else{
            dfs(root.left,target,sum);
            dfs(root.right,target,sum);
        }
        tmp.remove(tmp.size()-1);
    }

}

有注释版
注意两处细节

class Solution {

    // 用来存储结果
    private List<List<Integer>> res = new ArrayList();
    // 用来存贮路径
    // (先不向上转型,要使用LinkedList的API)
    // 你也可以使用 双端队列Deque
    //      但是Deque不能直接被list加入,需要调用 list.add(new ArrayList(deque));
    //                                               通过构造方法添加
    private LinkedList<Integer> path = new LinkedList<>();

    // 方案一: 这道题想都不用想,肯定DFS,深度搜索优先
    //                            从根节点出发,到叶子节点返回
    public List<List<Integer>> pathSum(TreeNode root, int target) {
        dfs(root, target);
        return res;
    }

    private void dfs(TreeNode root, int target) {
        // 递归截至条件
        if (root == null) {
            return;
        }
        // 减去当前node的值,并加入路径
        target -= root.val;
        path.add(root.val);
        // 题目必须要求,必须是叶子节点才行
        // 查看当前target消耗后是否为0,如果为0加入到结果中
        if (root.left == null && root.right == null
                && target == 0) {
            // 细节:为什么我要通过构造方法传入path,不能直接res.add(path)
            //      因为直接加入,加入的是引用(指向的堆中数据会变化),需要克隆一份加入
            res.add(new LinkedList<>(path));
            // 细节:找到后不能直接return,需要在path中移除最后一个元素,
            //      因为,即使你到根节点找到或找不到,该节点不能影响其他搜索
        }
        dfs(root.left, target);
        dfs(root.right, target);
        path.removeLast(); // 将本次搜索结果移除,方便其他搜索使用path变量
    }
}

NC9二叉树中是否存在节点和为指定值的路径

和前一题一样

NC14二叉树的之字形层序遍历

NC14 按之字形顺序打印二叉树

- 设计思想:
>定义一个队列
>往队列中加入当前节点
>当队列不为空的时候进行以下两个操作>
>1)求出当前队列的长度大小len。
>2)取出队列前len个节点,每取出一个节点,就把对应节点的左右孩子入队(前提左右孩子不为空)
>因为我们是之字形遍历,在遍历每一层节点的时候我们需要判断树的高度是不是奇偶,如果是偶数就倒着存储,如果是奇数就正着储存。
import java.util.*;

/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> res=new ArrayList<ArrayList<Integer>>();
        if(pRoot==null){
            return res;
        }

        // > 定义一个队列
        Queue<TreeNode> q=new LinkedList<>();

        // > 往队列中加入当前节点
        q.add(pRoot);
        int height=1;
        // > 当队列不为空的时候进行以下两个操作 >
        while(!q.isEmpty()){
            ArrayList<Integer> temp=new ArrayList<>();//存储每一层结点
            // > 1)求出当前队列的长度大小len。
            int len=q.size();
            // > 2)取出队列前len个节点,每取出一个节点,就把对应节点的左右孩子入队(前提左右孩子不为空)
            for(int i=0;i<len;i++){
                TreeNode node=q.poll();
        
                // > 因为我们是之字形遍历,在遍历每一层节点的时候我们需要判断树的高度是不是奇偶,如果是偶数就倒着存储,如果是奇数就正着储存。
                if(height%2==0){
                    temp.add(0,node.val);//插入到数组的最末尾
                }else{
                    temp.add(node.val);
                }
                

                if(node.left!=null){
                    q.add(node.left);
                }
                if(node.right!=null){
                    q.add(node.right);
                }
                
            }
           

            height++;//高度++
            res.add(new ArrayList<>(temp)); //把这一层的节点插入到res中
        }
        return res;
    }

}

2023-7-16 17:56:19

103. 二叉树的锯齿形层序遍历

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> ans=new LinkedList<List<Integer>>();
        if(root==null){
            return ans;
        }

        Queue<TreeNode> nodeQueue =new ArrayDeque<TreeNode>();
        nodeQueue.offer(root);
        boolean isOrderLeft=true;

        while(!nodeQueue.isEmpty()){
            Deque<Integer> levelList=new LinkedList<Integer>();
            int size=nodeQueue.size();
            for(int i=0;i<size;i++){
                TreeNode curNode=nodeQueue.poll();
                if(isOrderLeft){
                    levelList.offerLast(curNode.val);
                }else{
                    levelList.offerFirst(curNode.val);
                }
                if(curNode.left!=null){
                    nodeQueue.offer(curNode.left);
                }
                if(curNode.right!=null){
                    nodeQueue.offer(curNode.right);
                }
            }
            ans.add(new LinkedList<Integer>(levelList));
            isOrderLeft=!isOrderLeft;
        }
        
        return ans;
    
    }
}

2023-7-16 18:32:33

NC15 求二叉树的层序遍历

2023-3-9 21:10:48

NC15 求二叉树的层序遍历

思路比上一题简单

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */

public class Solution {
    /**
     * 
     * @param root TreeNode类 
     * @return int整型ArrayList<ArrayList<>>
     */
    public ArrayList<ArrayList<Integer>> levelOrder (TreeNode root) {
        // write code here
        ArrayList<ArrayList<Integer>> res=new ArrayList<>();
        if(root==null){
            return res;
        }
        Queue<TreeNode> q=new LinkedList<>();
        q.add(root);
        while(!q.isEmpty()){
            ArrayList<Integer> temp=new ArrayList<>();
            int len=q.size();
            for(int i=0;i<len;i++){
                TreeNode node=q.poll();
                temp.add(node.val);
                if(node.left!=null){
                    q.add(node.left);
                }
                if(node.right!=null){
                    q.add(node.right);
                }
            }
            res.add(new ArrayList<>(temp));
        }
        return res;
    }
}

2023-3-9 21:18:15

102. 二叉树的层序遍历

2023-7-16 18:41:55

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res=new ArrayList<List<Integer>>();

        if(root==null){
            return res;
        }

        Queue<TreeNode> q=new LinkedList<TreeNode>();
        q.add(root);

        while(!q.isEmpty()){
            ArrayList<Integer> temp=new ArrayList<>();
            
            int len=q.size();
            for(int i=0;i<len;i++){
                TreeNode cur=q.poll();
                temp.add(cur.val);
                if(cur.left!=null){
                    q.add(cur.left);
                }
                if(cur.right!=null){
                    q.add(cur.right);
                }
            }

            res.add(new ArrayList(temp));
        }
        return res;
    }
}

2023-7-16 18:41:55

NC37:合并区间

2023-3-9 21:18:19

NC37 合并区间

设计思想:
>这道题的基本思路就是先排序,在合并
>首先说排序:按照区间的左端点从小到大来排序区间
>排序好后我们就按照排序好后的区间进行操作
>首先定义两个变量l和r,l用来保存合并区间的左即start,r用来保存合并区间的右即end
然后使用指针r开始往后寻找,如果后续的区间的左端点即start比r小,就说明是重复区间,可以进行合并,然后更新合并区间的最大值即r>直到区间断开,然后将当前的l,r插入到答案里
>重复上述过程,直到全部区间遍历一次

import java.util.*;
/**
 * Definition for an interval.
 * public class Interval {
 *     int start;
 *     int end;
 *     Interval() { start = 0; end = 0; }
 *     Interval(int s, int e) { start = s; end = e; }
 * }
 */
public class Solution {
    public ArrayList<Interval> merge(ArrayList<Interval> intervals) {

        ArrayList<Interval> res=new ArrayList<>();

        // > 这道题的基本思路就是先排序,在合并
        // > 首先说排序: 按照区间的左端点从小到大来排序区间
        intervals.sort((a, b) -> (a.start - b.start));
        // > 排序好后我们就按照排序好后的区间进行操作
        // > 首先定义两个变量l和r,l用来保存合并区间的左即start,r用来保存合并区间的右即end
        int l,r;
        // 然后使用指针r开始往后寻找,如果后续的区间的左端点即start比r小,就说明是重复区间,可以进行合并,然后更新合并区间的最大值即r
        int i=0;
        while(i<intervals.size()){
            l=intervals.get(i).start;
            r=intervals.get(i).end;
            //合并区间
            while(i<intervals.size()-1&&r>=intervals.get(i+1).start){
                i++;
                r=Math.max(r,intervals.get(i).end);
            }
            // > 直到区间断开,然后将当前的1,r插入到答案里
            res.add(new Interval(l,r));
            i++;
            // > 重复上述过程,直到全部区间遍历一次

        }


        return res;
    }
}

56. 合并区间

2023-7-16 19:23:29

class Solution {
    public int[][] merge(int[][] intervals) {
        // 注:这里是通过List<int[]>来保存二维数组的;
    	// 通过List#add很方便;但在最后返回时要toArray(new int[0][])表示放到一个二维数组
        List<int[]> res = new ArrayList<>();
        if(intervals.length == 0 || intervals == null) return res.toArray(new int[0][]);       
        // 1.排序
    	// 这里通过lamada用函数式接口,实现了Comptor接口;表示比较两个一维数组i1,i2通过i[0]比较
         Arrays.sort(intervals, (i1, i2) -> i1[0] - i2[0]);
        // 2.初始区间
        int start = intervals[0][0], end = intervals[0][1];
    	// 3.创建区间
        for(int[] arr:intervals){
            if(arr[0]<=end){
                end=Math.max(end,arr[1]);
            }else{
                res.add(new int[]{start,end});
                start=arr[0];
                end=arr[1];
            }
        }
    	// 4.剩余处理
        res.add(new int[]{start, end});
        return res.toArray(new int[0][]);        

    }
}
class Solution {
    public int[][] merge(int[][] intervals) {
        if(intervals.length==0){
            return new int[0][2];
        }
        //首先,我们将列表中的区间按照左端点升序排序。
        Arrays.sort(intervals,new Comparator<int[]>(){
            public int compare(int[] interval1,int[] interval2){
                return interval1[0]-interval2[0];
            }
        });

        List<int[]> merged=new ArrayList<>();
        for(int i=0;i<intervals.length;i++){
            int L=intervals[i][0],R=intervals[i][1];
            //然后我们将第一个区间加入 merged 数组中,并按顺序依次考虑之后的每个区间:
            //如果当前区间的左端点在数组 merged 中最后一个区间的右端点之后,那么它们不会重合,
            if(merged.size()==0||merged.get(merged.size()-1)[1]<L){
                //我们可以直接将这个区间加入数组 merged 的末尾;
                merged.add(new int[]{L,R});
            }else{//否则,它们重合,
                //我们需要用当前区间的右端点更新数组 merged 中最后一个区间的右端点,
                //将其置为二者的较大值。
                merged.get(merged.size()-1)[1]=Math.max(merged.get(merged.size()-1)[1],R);
            }
        }
        return merged.toArray(new int[merged.size()][]);
    }
}

2023-7-16 19:42:57

NC111 最大数

2023-3-9 21:43:27

NC111 最大数

-3、设计思想:
>这道题题目已经提示,输出用字符串的形式了,所以我们第一步就是把整数数组变为字符串数组。
>第二步呢就是将字符串数组排序,那么排序规则是什么呢?
>排序规则就是:每次将相邻的两个字符串正反拼接,然后比大小,从而确定相邻的两个字符串是否交换位置。
>还有一个细节就是如果排序好的数组第一个元素就是”O”,那么结果直接返回字符串”O”就好了。
>如果排序好后的数组第一个元素不是”O,那么直接从头到尾拼接返回就好了。
import java.util.*;


public class Solution {
    /**
     * 最大数
     * @param nums int整型一维数组
     * @return string字符串
     */
    public String solve (int[] nums) {
        // write code here

        // > 这道题题目已经提示,输出用字符串的形式了,所以我们第一步就是把整数数组变为字符串数组。
        ArrayList<String> list = new ArrayList<>();
        for (int i = 0; i < nums.length; i++) {
            list.add(String.valueOf(nums[i]));
        }
        // > 第二步呢就是将字符串数组排序,那么排序规则是什么呢 ?
        // >排序规则就是 :
        // 每次将相邻的两个字符串正反拼接,然后比大小,从而确定相邻的两个字符串是否交换位置。
        Collections.sort(list, new Comparator<String>() {
            public int compare(String a, String b) {
                return (b + a).compareTo(a + b);
            }
        });
        // > 还有一个细节就是如果排序好的数组第一个元素就是”O”,那么结果直接返回字符串”O”就好了。
        if (list.get(0).equals("0")) return "0";
        // > 如果排序好后的数组第一个元素不是”O”,
        // 那么直接从头到尾拼接返回就好了。
        StringBuilder res = new StringBuilder(); 
        for (int i = 0; i < list.size();i ++) { 
            res.append(list.get(i));
        }
        return res.toString();
    }
}

NC16 判断二叉树是否对称

NC16 对称的二叉树

/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    boolean isSymmetrical(TreeNode pRoot) {
        if (pRoot == null) {
            return true;
        }
        return like(pRoot.left, pRoot.right);

    }

    boolean like(TreeNode pLeft, TreeNode pRight) {
        if (pLeft==null&&pRight==null){
            return true;
        }
        if (pLeft == null || pRight  == null) {
            return false;
        }
        return pLeft.val == pRight.val 
            && like(pLeft.left,pRight.right)
            && like(pLeft.right,pRight.left);
    }
}

NC13 二叉树的最大深度

NC13 二叉树的最大深度

思路
树的高度=max(左子树的高度,右子树的高度)+1
import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */

public class Solution {

    int height=1;

    /**
     * 
     * @param root TreeNode类 
     * @return int整型
     */
    public int maxDepth (TreeNode root) {
        // write code here
        if(root==null){
            return 0;
        }
        int lh=maxDepth(root.left);
        int rh=maxDepth(root.right);
        return Math.max(lh,rh)+1;
    }
  
}

2023-3-9 22:17:32

NC62 平衡二叉树

NC62 判断是不是平衡二叉树

public class Solution {
    public boolean IsBalanced_Solution(TreeNode root) {
        if (root == null) {
            return true;
        }
        return Math.abs(getHeight(root.left)-getHeight(root.right))<=1
            &&IsBalanced_Solution(root.left)
            &&IsBalanced_Solution(root.right);
    }

    public int getHeight(TreeNode root){
        if(root == null) return 0;
        int lh = getHeight(root.left);
        int rh = getHeight(root.right);
        return Math.max(lh,rh) + 1;
    }
}

2023-3-9 22:23:51

NC7:股票(一次交易)

2023-3-9 22:24:35

NC7 买卖股票的最好时机(一)

-3、 设计思想:
>我们先解读题意,题目中给了两个限定条件:1)只能有一次买入和卖出2)只有买入了股票以后才能卖出,
>因此我们就定义一个状态,即dp[i][j](其中j = 01),dp[i][0]代表下标为i天的时候手上没有股票,最大正收益为多少,
>dp[i][1]代表下表为i天的时候,手上有股票,最小负收益为多少。
>此时我们定义初始状态dp[0][0] = 0, dp[i][1] = prices[0]
>我们定义好dp方程式后我们开始来推转移方程。
>dp[i][o] = max(dp[i-1][o], prices[i] - dp[i-1][1])
>dp[i][1]= min(dp[i-1][1], prices[i]);
>最后返回dp[prices-1][0]即为所求

当我们到读懂了上面的方程后,我们可以把二维空间优化为一维空间,因为你会发现这道题只有2种依态就是0:代表卖股票,1:代表持有股票。也就是说我们只需要求得dp[0]的最大值,所以将方程变为
dp[0] = max(dp [0] , prices[i] - dp[1]);
dp[1] = min(dp[1], prices[i]);

当我们看完上一张ppt时优化后的方程,我们知道因为只有两种状态,那么我们连数组都不需要开,所以直接定义两个变量就好了min_input:代表你买入的股票价钱即上一张ppt的dp[1],max_output:代表你卖出股票价钱即上一张ppt的dp[0],所以方程如下:
min_input = min(min_input, prices[i]);
max_output = max (max_output.prices[i]-min_input) ;

import java.util.*;


public class Solution {
    /**
     *
     * @param prices int整型一维数组
     * @return int整型
     */
    public int maxProfit (int[] prices) {
        // write code here

        //>我们先解读题意,题目中给了两个限定条件:1)只能有一次买入和卖出2)只有买入了股票以后才能卖出,
        // >因此我们就定义一个状态,即dp[i][j](其中j = 0或1),dp[i][0]代表下标为i天的时候手上没有股票,最大正收益为多少,       
        // >dp[i][1]代表下表为i天的时候,手上有股票,最小负收益为多少。
        int [][] dp=new int[prices.length][2];
        // >此时我们定义初始状态dp[0][0] = 0, dp[i][1] = prices[0]
        dp[0][0] = 0;
        for(int i=0;i<dp.length;i++){
            dp[i][1] = prices[0];
        }
        
        // >我们定义好dp方程式后我们开始来推转移方程。
        // >dp[i][0] = max(dp[i-1][0], prices[i] - dp[i-1][1])
        // >dp[i][1]= min(dp[i-1][1], prices[i]);

        for(int i=1;i<dp.length;i++){
            dp[i][0] = Math.max(dp[i-1][0], prices[i] - dp[i-1][1]);
            dp[i][1]= Math.min(dp[i-1][1], prices[i]);
        }
        
        // >最后返回dp[prices-1][0]即为所求
        return dp[dp.length-1][0];
    }
}

2023-3-9 22:42:32

NC22 合并两个有序的数组

NC22 合并两个有序的数组

import java.util.*;
public class Solution {
    public void merge(int A[], int m, int B[], int n) {
        int i=0;//用来遍历B
        int j=0;//用来遍历A
        while(i<n){
            while(B[i]>=A[j]&&j<m){//找到比B大的A元素的位置j
                j++;
            }
            if(j>m){//如果找到最后都没有就在最后插入
                put(A,m++,j,B[i]);//因为添加了一个,A的长度m+1
            }   
            put(A,m++,j,B[i]);//因为添加了一个,A的长度m+1
            i++;      
        }
    }
    public void put(int A[], int m,int j,int n){//在j的位置插入元素n
        for(int i=m;i>j;i--){
            A[i]=A[i-1];
        }
        A[j]=n;
        System.out.println(Arrays.toString(A));
    }
}

2023-3-9 23:22:56

NC52括号序列

2023-3-10 10:40:10

NC52 有效括号序列

import java.util.*;


public class Solution {
    /**
     * 
     * @param s string字符串 
     * @return bool布尔型
     */
    public boolean isValid (String s) {
        // write code here
        Stack<Character> st=new Stack<>();
        char[] chars=s.toCharArray();
        for(int i=0;i<chars.length;i++){//遍历字符数组
            if(left(chars[i])){//左括号入栈
                st.push(chars[i]);
            }
            if(right(chars[i])){//右括号
                if(st.isEmpty()){//如果栈为空,没有匹配的左括号
                    return false;
                }
                boolean p=match(st.pop(),chars[i]);//匹配栈顶左括号
                if(p==false){//匹配失败
                    return false;

                }
            }
        }
        return st.isEmpty();//判断有没有多余的左括号
    }

    public boolean left(char c){
        return c=='('||c=='['||c=='{';
    }
    public boolean right(char c){
        return c==')'||c==']'||c=='}';
    }
    public boolean match(char c1,char c2){
        if(c1=='('&&c2==')') return true;
        if(c1=='['&&c2==']') return true;
        if(c1=='{'&&c2=='}') return true;
        return false;
    } 
}

2023-3-10 11:12:23

NC102 最近公共祖先

2023-3-10 11:13:19

NC102 在二叉树中找到两个节点的最近公共祖先

设计思想:
>对于树的题我们第一想法就是递归,那么对于这道题,我们同样是递归查询两个给定的两个节点o1, o2
>如果这棵树中的某个节点等于节点o1或者o2,那么就向上返回这个节点给父节点
>如果当前节点的左右子树返回值分别是o1、o2,那么当前这个节点就是最近公共祖先
>如果当前节点只有一个子树的返回值为o1或o2节点,则返回该值
>如果当前节点的两个子树返回值都为空,则返回空指针。
import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */

public class Solution {
    /**
     *
     * @param root TreeNode类
     * @param o1 int整型
     * @param o2 int整型
     * @return int整型
     */
    public int lowestCommonAncestor (TreeNode root, int o1, int o2) {
        // write code here
        return dfs(root,o1,o2).val;
    }
    
    //> 对于树的题我们第一想法就是递归,那么对于这道题,我们同样是递归查询两个给定的两个节点o1,o2
    public TreeNode dfs(TreeNode root,int o1,int o2){
        //> 如果这棵树中的某个节点等于节点o1或者o2,那么就向上返回这个节点给父节点
        //> 如果当前节点的两个子树返回值都为空,则返回空指针。
        if(root==null||root.val==o1||root.val==o2){
            return root;
        }
        TreeNode left=dfs(root.left,o1,o2);
        TreeNode right=dfs(root.right,o1,o2);
        //> 如果当前节点的左右子树返回值分别是o1、o2,那么当前这个节点就是最近公共祖先
        if(left!=null&&right!=null){
            return root;
        }
        //> 如果当前节点只有一个子树的返回值为o1或o2节点,则返回该值
        return left==null?right:left;

    }
}

2023-3-10 11:24:24

NC78 反转链表

2023-3-10 11:25:28

NC78 反转链表

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode ReverseList(ListNode head) {
        ListNode res=null;
        ListNode c=head;
        while(c!=null){
            ListNode n=c.next;//记录下一个结点
            c.next=res;
            res=c;
            c=n;//遍历
        }
        return res;
    }
}

2023-3-10 11:33:04

NC103 反转字符串

2023-3-10 11:34:07

NC103 反转字符串

import java.util.*;


public class Solution {
    /**
     * 反转字符串
     * @param str string字符串 
     * @return string字符串
     */
    public String solve (String str) {
        // write code here
        char [] chars=str.toCharArray();
        for(int i=0;i<chars.length/2;i++){
            char temp=chars[i];
            chars[i]=chars[chars.length-1-i];
            chars[chars.length-1-i]=temp;
        }
        return new String(chars);
    }
}

2023-3-10 11:38:13

NC33 合并有序链表

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if(list1==null) return list2;
        if(list2==null) return list1;
        ListNode res=new ListNode(-1);//虚拟结点
        ListNode cur1=list1;//遍历1
        ListNode cur2=list2;//遍历2
        ListNode cur=res;//遍历res
        while(cur1!=null&&cur2!=null){
            if(cur1.val<=cur2.val){
                cur.next=cur1;
                cur=cur1;
                cur1=cur1.next;
            }else{
                cur.next=cur2;
                cur=cur2;
                cur2=cur2.next;
            }
        }
        if(cur1!=null) cur.next=cur1;
        if(cur2!=null) cur.next=cur2;
        return res.next;
    }
}

2023-3-10 11:46:22

NC75数组中只出现一次的数字(哈希法)

NC75 数组中只出现一次的两个数字

2023-3-10 11:47:31

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param array int整型一维数组 
     * @return int整型一维数组
     */
    public int[] FindNumsAppearOnce (int[] array) {
        // write code here
        int[] res=new int[2];
        HashMap<Integer,Integer> map=new HashMap<>();
        for(int i:array){
            if(!map.containsKey(i)){
                map.put(i,1);
            }else{
                map.put(i,map.get(i)+1);
            }
            
        }
        int cnt=0;
        for(int i=0;i<array.length;i++){
            if(map.get(array[i])==1){
                res[cnt++]=array[i];
            }
            if(cnt==2){
                break;
            }
        }
        if(res[0]>res[1]){
            return new int[]{res[1],res[0]};
        }
        return res;
    }
}

2023-3-10 11:55:19

NC75数组中只出现一次的数字(位运算法)

2023-3-10 16:31:36

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param array int整型一维数组 
     * @return int整型一维数组
     */
    public int[] FindNumsAppearOnce (int[] array) {
        // write code here
        int s=0;
        for(int n:array){
            s^=n;
        }    
        int rightOne=s&(~s+1);// 提取出最右的1

        int one=0;
        for(int n:array){
            if((n&rightOne)!=0){
                one^=n;
            }
        }

        int other=one^s;

        if(one>other){
            return new int[]{other,one};
        }else{
            return new int[]{one,other};
        }

    }
}

2023-3-10 16:40:42

NC61两数之和(暴力)

2023-3-10 16:41:28
NC61 两数之和

会运行超时

import java.util.*;


public class Solution {
    /**
     * 
     * @param numbers int整型一维数组 
     * @param target int整型 
     * @return int整型一维数组
     */
    public int[] twoSum (int[] numbers, int target) {
        // write code here
        for(int i=0;i<numbers.length;i++){
            for(int j=i+1;j<numbers.length;j++){
                if(numbers[i]+numbers[j]==target){
                    return new int[]{i+1,j+1};
                }
            }
        }
        return new int[2];
    }
}

2023-3-10 16:47:47

NC61两数之和(哈希法)

import java.util.*;


public class Solution {
    /**
     * 
     * @param numbers int整型一维数组 
     * @param target int整型 
     * @return int整型一维数组
     */
    public int[] twoSum (int[] numbers, int target) {
        // write code here
        HashMap<Integer,Integer> map=new HashMap<>();
        for(int i=0;i<numbers.length;i++){
            if(!map.containsKey(target-numbers[i])){
                map.put(numbers[i],i);
            }else{
                return new int[]{map.get(target-numbers[i])+1,i+1};
            }
        }
        return new int[2];
    }
}

2023-3-10 16:52:30

NC59矩阵的最小路径和

2023-3-10 16:53:37

NC59 矩阵的最小路径和

-3、设计思想:
>定义一个dp大小为n×m 矩阵,其中 dp[i][j]的值代表走到(i,j)的最小路径和
>当i = 0, j = 0时,dp[i][j] = matrix [i][j]
>当i = 0, j != 0, dp[i][j] = dp[0][j-1] +matrix[0][j]//第0列就是从0,0到n-1,0
>当i != 0,j = 0, dp[i][j] = dp[i-1][0] +matrix[i][0] //第0行就是从0,0到0,m-1
>当i != 0, j != 0,dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + matrix[i][j] //比较 向下走和向右走哪个更短
>最后返回值为dp[n-1][m-1]
import java.util.*;


public class Solution {
    /**
     *
     * @param matrix int整型二维数组 the matrix
     * @return int整型
     */
    public int minPathSum (int[][] matrix) {
        // write code here
        // >定义一个dp大小为n×m 矩阵,其中 dp[i][j]的值代表走到(i,j)的最小路径和
        int n=matrix.length;
        int m=matrix[0].length;
        int [][] dp=new int [n][m];
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                // >当i = 0, j = 0时,dp[i][j] = matrix [i][j]
                if(i==0&&j==0){
                    dp[i][j]=matrix[i][j];
                }
                // >当i = 0, j != 0时, dp[i][j] = dp[0][j-1] +matrix[0][j]
                if(i==0&&j!=0){
                    dp[i][j] = dp[0][j-1] +matrix[0][j];
                }
                // >当i != 0,j = 0时, dp[i][j] = dp[i-1][0] +matrix[i][0]
                if(i!=0&&j==0){
                    dp[i][j] = dp[i-1][0] +matrix[i][0];
                }
                // >当i != 0, j != 0时,dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + matrix[i][j]
                if(i!=0&&j!=0){
                    dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + matrix[i][j];
                }
            }
        }

        // >最后返回值为dp[n-1][m-1]。
        return dp[n-1][m-1];



    }



}

2023-3-10 17:07:51

NC19子数组的最大累加和问题

2023-3-10 17:08:51

NC19 连续子数组的最大和

3、设计思想:
>定义一个dp大小为n的数组,其中 dp[i]的值代表到第i位的时侯,以arr[i]结尾的连续子数组最大累加和。
>当i = 0 时,dp[i] = arr[0]
>当i != 0时,dp[i] = max(0,dp[i-1]) + arr[i](若dp[i-1]<=0 时dl[i-1] + ari还不arr[i]的本身大,
所以当dp[i-1]<=0时 dp[i]=array[i] 当p[i-1]>0时dp[i]=dp[i-1]+array[i]
>最后返回值为dp数组中最大的值

public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) {

        // >定义一个dp大小为n的数组,其中 dp[i]的值代表到第i位的时侯,以arr[i]结尾的连续子数组最大累加和。
        int len = array.length;
        int[] dp = new int[len];
        // >当i = 0 时,dp[i] = arr[0]
        dp[0]=array[0];
        // >当i != 0时,dp[i] = max(0,dp[i-1]) + arr[i](若dp[i-1]<=0 时dl[i-1] + ari还不arr[i]的本身大,
        // 所以当dp[i-1]<=0时 dp[i]=array[i] 当p[i-1]>0时dp[i]=dp[i-1]+array[i] 
        for (int i = 1; i < len; i++) {
            dp[i] = Math.max(0,dp[i - 1]) + array[i];
        }
        // >最后返回值为dp数组中最大的值
        int res=dp[0];
       for (int i = 1; i < len; i++) {
            res = Math.max(res,dp[i]);
        }
        return res;

    }
}

2023-3-10 17:25:25

NC4判断链表中是否有环

NC4 判断链表中是否有环

import java.util.*;

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
       //hash
       HashSet<ListNode> set=new HashSet<>();
       ListNode p=head;
       while(p!=null){
        if(set.contains(p)){
            return true;
        }else{
            set.add(p);
        }

        p=p.next;
       }

       return false;
    }
}

2023-3-10 17:37:47

NC4判断链表中是否有环(空间复杂度o(1))

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head==null){
            return false;
        }
        //双指针
        ListNode p=head;
        ListNode q=head.next;
        while(p!=q&&p!=null&&q!=null){
            p=p.next;
            if(q.next!=null){
                q=q.next.next;
            }else{
                return false;
            }
            
        }
        return (p!=null&&q!=null)?true:false;
    }
}

2023-3-10 17:33:28

NC34求路径

NC34 不同路径的数目(一)

-3、设计思想:
>定义一个dp大小为m×n矩阵,其中 dp[i][j的值代表走到(i,j)的路径种类。
>当i = 0,j >= 0, dp[i][j] = 1,因为机器人只能从左边过来,所以只有一种方案
>当i >= 0, j = 0, dp[i][j] = 1,因为机器人只能从上边过来,所以只有一种方案
>当i !=0, j !=0,  dp[i][j]=dp[i - 1][j]+ dp[i][j -1]因为到达(i,j)只有两种策略
	1)机器人从点(i-1, j)往下移动	2)机器人从点(i,j-1)往右移动,
	所以dpl[i][j]=二者的总和
>最后返回值为dp[m-1][n-1]
import java.util.*;


public class Solution {
    /**
     * 
     * @param m int整型 
     * @param n int整型 
     * @return int整型
     */
    public int uniquePaths (int m, int n) {
        // write code here
        //>定义一个dp大小为m×n矩阵,其中 dp[i][j的值代表走到(i,j)的路径种类。
        int dp[][]=new int[m][n];
        
        // >当i = 0,j >= 0时, dp[i][j] = 1,因为机器人只能从左边过来,所以只有一种方案
        for(int j=0;j<n;j++){
            dp[0][j]=1;
        }
        // >当i >= 0, j = 0时, dp[i][j] = 1,因为机器人只能从上边过来,所以只有一种方案
        for(int i=0;i<m;i++){
            dp[i][0]=1;
        }
        // >当i !=0, j !=0 时,  dp[i][j]=dp[i - 1][j]+ dp[i][j -1]因为到达(i,j)只有两种策略
        // 	1)机器人从点(i-1, j)往下移动   2)机器人从点(i,j-1)往右移动,
        // 	所以dpl[i][j]=二者的总和
        for(int i=1;i<m;i++){
            for(int j=1;j<n;j++){
                dp[i][j]=dp[i-1][j]+dp[i][j-1];    
            }
        }
          
        // >最后返回值为dp[n-1][m-1]。
        return dp[m-1][n-1];
    }
}

2023-3-12 13:45:22

NC68跳台阶

NC68 跳台阶

-3、 设计思想:
>按照题解直接写这道题就好了,
>当只有1个台阶的时候,只有一种方法
>当有2个台阶的时候,有2种跳法1)一次跳1个,2)一次跳2>当有n个台阶的时候,它可以从n-1个台阶跳过来,也可以从n-2个台阶跳过来
>所以n台阶种类= n-1台阶种类+ n-2台阶种类

public class Solution {
    public int jumpFloor(int target) {
        int [] dp=new int[target+1];
        
        for(int i=0;i<target+1;i++){
            // >当只有1个台阶的时候,只有一种方法
            if(i==0||i==1){
                dp[i]=1;
            }else{
                // >当有2个台阶的时候,有2种跳法1)一次跳1个,2)一次跳2个
                // >当有n个台阶的时候,它可以从n-1个台阶跳过来,也可以从n-2个台阶跳过来
                // >所以n台阶种类= n-1台阶种类+ n-2台阶种类
                dp[i]=dp[i-1]+dp[i-2];
            }
            
            
        }
        
        return dp[target];
    }
}

2023-3-12 13:52:15

NC112进制转换

2023-3-12 13:53:41

NC112 进制转换

import java.util.*;


public class Solution {
    /**
     * 进制转换
     * @param M int整型 给定整数
     * @param N int整型 转换到的进制
     * @return string字符串
     */
    public String solve (int M, int N) {
        // write code here
        if(M==0){
            return "0";
        }
        boolean flag=false;
        if(M<0){
            flag=true;
            M=-M;
        }
        StringBuilder sb=new StringBuilder();
        while(M!=0){
            int m=M%N;
            char c;
            if(m>=10){
                c=(char)('A'+(m-10));
            }else{
                c=(char)('0'+(m-0));
            }
            sb.append(c);
            M/=N;
        }
        if(flag==true){
            sb.append('-');
        }
        sb.reverse();
        return sb.toString();
    }
   
}

2023-3-12 14:05:12

NC65斐波那契数列

2023-3-12 14:06:02

NC65 斐波那契数列

public class Solution {
    public int Fibonacci(int n) {
        if(n==1||n==2){
            return 1;
        }else{
            return Fibonacci(n-1)+Fibonacci(n-2);
        }
    }
}

2023-3-12 14:07:01

NC76用两个栈实现队列

2023-3-12 14:08:23

NC76 用两个栈实现队列

import java.util.Stack;

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    
    public void push(int node) {
        //栈1不为空,直接入栈 否则把栈2的内容倒回来
        if(!stack1.isEmpty()){
            stack1.push(node);
        }else{
            while(!stack2.isEmpty()){
                stack1.push(stack2.pop());
            }
            stack1.push(node);
        }
        
    }
    
    public int pop() {
        //栈2不为空,直接出栈 否则把栈1的内容倒出来
        if(!stack2.isEmpty()){
            return stack2.pop();
        }
        while(!stack1.isEmpty()){
            stack2.push(stack1.pop());
        }
        return stack2.pop();
    }
}


2023-3-12 14:18:11

NC41 最长无重复子串

NC41 最长无重复子数组

import java.util.*;


public class Solution {
    /**
     * 
     * @param arr int整型一维数组 the array
     * @return int整型
     */
    public int maxLength (int[] arr) {
        // write code here
        HashSet<Integer> set=new HashSet<>();
        int l=0;
        int r=0;
        int cnt=1;//长度
        while(l<arr.length&&r<arr.length){
            if(!set.contains(arr[r])){
                set.add(arr[r]);
                r++;
                cnt=Math.max(cnt,r-l);
            }else{
                set.remove(arr[l]);
                l++;
            }
            
        }
        return cnt;
    }
}

2023-3-12 14:30:27

NC133链表的奇偶重排

NC133 链表的奇偶重排

import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 *   public ListNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 
     * @param head ListNode类 
     * @return ListNode类
     */
    public ListNode oddEvenList (ListNode head) {
        // write code here
        ListNode res1=new ListNode(-1);
        ListNode res2=new ListNode(-1);
        int cnt=1;
        ListNode cur=head;
        ListNode cur1=res1;
        ListNode cur2=res2;
        while(cur!=null){
            if(cnt%2==1){
                cur1.next=cur;
                cur1=cur;
            }else{
                cur2.next=cur;
                cur2=cur;
            }
            cur=cur.next;
            cnt++;
        }
        cur2.next=null;
        cur1.next=res2.next;
        return res1.next;
    }
}

2023-3-12 14:46:09

NC116把数字翻译成字符串

2023-3-12 14:47:58

NC116 把数字翻译成字符串

import java.util.*;


public class Solution {
    /**
     * 解码
     * @param nums string字符串 数字串
     * @return int整型
     */
    public int solve (String nums) {
        // write code here
        if(nums.charAt(0)=='0') return 0;

        int [] dp=new int[nums.length()];//dp[i]的含义代表长度在i位置时有几种翻译办法
        dp[0]=1;//在第0个字符的时候只有一个字母所以只有一种翻译办法
        for(int i=1;i<dp.length;i++){
            if(nums.charAt(i)=='0'){
                if(nums.charAt(i-1)=='1'||nums.charAt(i-1)=='2'){
                    if(i==1) dp[i]=1;//特判字符串长度为2
                    else dp[i]=dp[i-2];//因为 10 20 这样的只有一种对应方案,所以此时dp[i]取决于dp[i-2]
                }
            }else if(nums.charAt(i-1)=='1'||
            (nums.charAt(i-1)=='2'&&nums.charAt(i)>='1'&&nums.charAt(i)<='6')){
                /*11-26 抛去 20这样的组合
                但是当i==1的时候如 12 21 这样有两种方案
                当i>1时候dp[i] 取决于 dp[i-1] 和 dp[i-2]的和
                */
                if(i==1) dp[i]=2;
                else dp[i]=dp[i-1]+dp[i-2];
            }else{
                dp[i]=dp[i-1];
            }
        }
        return dp[dp.length-1];
    }
}

2023-3-12 15:03:03

NC135股票(两次交易)

2023-3-12 15:04:09

NC135 买卖股票的最好时机(三)

-3、设计思想:
>我们先解读题意,题目中给了一个限定条件:最多买卖两次,也就是说他与股票(一次交易不同)点就是多了一次交易。但是多了一次交易就会产生巨大的变化。
>股票(一次交易)只有两个状态,但是本题就5个状态: 1)不操作2)第一次购买3)第一次卖出4)第二次购买5)第二次卖出
即db[i][j]代表第i天状态为j时产生的最大收益
>dp[i][0]代表下标为i天的时候,手上没有股票,最大收益
>dp[i][1]代表下表为i天的时候,第一次购买,手上有股票,最大收益
>dp[i][2]代表下表为i天的时候,第一次卖出,手上无股票,最大收益
>dp[i][3]代表下表为i天的时候,第二次购买,手上有股票,最大收益
>dp[i][4]代表下表为i天的时候,第二次卖出,手上五股票,最大收益
>来看初始化,第0天没有操作,所以dp[0][0]= o
>0天做第一次买入, dp[0][1] = -prices[0]
>0天做第一次卖出, dp[0][2]= 0
>0天做第二次买入, dp[0][3] = -prices[0]
>0天做第二次卖出, dp[0][4]=0 
>来看状态方程:
>dp[i][0]= dp[i-1][0]
>dp[i][1]= max(dp[i-1][1],dp[i-1][0]-prices[i]),其中dp[i][1]有两个操作1)第i天没有操作2)第i天买入股票,所以此时最大收益,应为这两个操作比大小
>dp[i][2] = max(dp[i-1][2],dp[i-1][1]+ prices[i]),其中dp[i][2]有两个操作1)第i天没有操作2)第i天卖出股票,所以此时最大收益,应该为这两个操作比大小
>dp[i][3] = max(dp[i-1][3],dp[i-1][2]-prices[i]),其中dp[i][3]有两个操作1)第i天没有操作2)第i天买入股票,所以此时最大收益,应该为这两个操作比大小
>dp[i][4]= max(dp[i-1][4],dp[i-1][3]+ prices[i]),其中dp[i][4]有两个操作1)第i天没有操作2)第i天卖出股票,所以此时最大收益,应该为这两个操作比大小
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 两次交易所能获得的最大收益
     * @param prices int整型一维数组 股票每一天的价格
     * @return int整型
     */
    public int maxProfit (int[] prices) {
        // write code here
        // >我们先解读题意,题目中给了一个限定条件:最多买卖两次,也就是说他与股票(一次交易不同)点就是多了一次交易。但是多了一次交易就会产生巨大的变化。
        // >股票(一次交易)只有两个状态,但是本题就5个状态: 1)不操作2)第一次购买3)第一次卖出4)第二次购买5)第二次卖出
        // 即db[i][j]代表第i天状态为j时产生的最大收益
        // >dp[i][0]代表下标为i天的时候,手上没有股票,最大收益
        // >dp[i][1]代表下表为i天的时候,第一次购买,手上有股票,最大收益
        // >dp[i][2]代表下表为i天的时候,第一次卖出,手上无股票,最大收益
        // >dp[i][3]代表下表为i天的时候,第二次购买,手上有股票,最大收益
        // >dp[i][4]代表下表为i天的时候,第二次卖出,手上五股票,最大收益
        int n=prices.length;
        int [][]dp =new int[n][5];
        // >来看初始化,第0天没有操作,所以dp[0][0]= 0
        // >第0天做第一次买入, dp[0][1] = -prices[0]
        // >第0天做第一次卖出, dp[0][2]= 0
        // >第0天做第二次买入, dp[0][3] = -prices[0]
        // >第0天做第二次卖出, dp[0][4]=0 
        dp[0][0]=0;
        dp[0][1]=-prices[0];
        dp[0][2]=0;
        dp[0][3] = -prices[0];
        dp[0][4]=0;
        // >来看状态方程:
        for(int i=1;i<n;i++){
            // >dp[i][0]= dp[i-1][0]
            dp[i][0]= dp[i-1][0];
            // >dp[i][1]= max(dp[i-1][1],dp[i-1][0]-prices[i]),其中dp[i][1]有两个操作1)第i天没有操作2)第i天买入股票,所以此时最大收益,应为这两个操作比大小
            dp[i][1]= Math.max(dp[i-1][1],dp[i-1][0]-prices[i]);
            // >dp[i][2] = max(dp[i-i][2],dp[i-1][1]+ prices[i]),其中dp[i][2]有两个操作1)第i天没有操作2)第i天卖出股票,所以此时最大收益,应该为这两个操作比大小
            dp[i][2] = Math.max(dp[i-1][2],dp[i-1][1]+ prices[i]);
            // >dp[i][3] = max(dp[i-1][3],dp[i-1][2]-prices[i]),其中dp[i][3]有两个操作1)第i天没有操作2)第i天买入股票,所以此时最大收益,应该为这两个操作比大小
            dp[i][3] = Math.max(dp[i-1][3],dp[i-1][2]-prices[i]);
            // >dp[i][4]= max(dp[i][4],dp[i-1][3]+ prices[i]),其中dp[i][4]有两个操作1)第i天没有操作2)第i天卖出股票,所以此时最大收益,应该为这两个操作比大小
            dp[i][4]= Math.max(dp[i-1][4],dp[i-1][3]+ prices[i]);
        }
         return dp[n - 1][4];
    }
}

2023-3-12 15:29:28

NC126换钱的最少货币数

2023-3-12 15:30:08

NC126 兑换零钱(一)

-3、 设计思想:
>这道题你读完就会发现是完全背包问题,如果你看过背包9讲,这个题非常简单了。
>首先我们定义一个dp[i]代表给定钱数为i的时候最少货币数是多少
>然后我们确定状态转移方程,假如给定钱币数为i那么它的换钱方案将由两个方案1)没办法兑换钱币arr[i]所以dp[i]=dp[i] 2)arr[i]可以兑换,那么dp[i]=dp[i-arr[i]+1]。所以dp[i]=min(dp[i],dp[i-arr[i]])
>初始化dp数组,首先当给定钱数为0的时候,不需要兑换钱币,所以dp[O]=0,但是我们要找一个最小值,所以需要将下标非0的元素初始化为一个很大的
import java.util.*;


public class Solution {
    /**
     * 最少货币数
     * @param arr int整型一维数组 the array
     * @param aim int整型 the target
     * @return int整型
     */
    public int minMoney (int[] arr, int aim) {
        // write code here
        // >这道题你读完就会发现是完全背包问题,如果你看过背包9讲,这个题非常简单了。
        int Max=aim+1;//定义一个全局最大数
        // >首先我们定义一个dp[i]代表给定钱数为i的时候最少货币数是多少
        int [] dp=new int[aim+1];
        Arrays.fill(dp,Max);//把dp数组全部定为最大值
        // >然后我们确定状态转移方程,假如给定钱币数为i那么它的换钱方案将由两个方案1)没办法兑换钱币arr[i]所以dp[i]=dp[i] 2)arr[i]可以兑换,那么dp[i]=dp[i-arr[i]+1]。所以dp[i]=min(dp[i],dp[i-arr[i]])
        
        // >初始化dp数组,首先当给定钱数为0的时候,不需要兑换钱币,所以dp[O]=0,但是我们要找一个最小值,所以需要将下标非0的元素初始化为一个很大的
        dp[0]=0;
        for(int i = 1;i <= aim;i ++){// 遍历目标值
            for(int j = 0;j < arr.length;j ++){// 遍历钱币
                if(arr[j] <= i){//如果当前的钱币比目标值小就可以兑换
                    dp[i] = Math.min(dp[i],dp[i-arr[j]] + 1);


                }
            }
        }
        return dp[aim] > aim ? -1 : dp[aim];
    }
}

2023-3-12 15:42:35

NC45实现二叉树先序,中序和后序遍历(递归)

NC45 实现二叉树先序,中序和后序遍历

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */

public class Solution {

    ArrayList<Integer> pre=new ArrayList<>();
    ArrayList<Integer> in=new ArrayList<>();
    ArrayList<Integer> post=new ArrayList<>();
    /**
     * 
     * @param root TreeNode类 the root of binary tree
     * @return int整型二维数组
     */
    public int[][] threeOrders (TreeNode root) {
        // write code here
        if(root == null) return new int[][]{{},{},{}};//根节点为空直接返回
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();//临时存储最终结果
        preOrders(root);
        inOrders(root);
        postOrders(root);
        res.add(new ArrayList(pre));//将先序遍历放进res
        res.add(new ArrayList(in));//将中序遍历放进res
        res.add(new ArrayList(post));//将后序遍历放进res
        int [][]ans = new int[res.size()][res.get(0).size()];//用于返回最终的结果
        ///需要将res的结果复制到ans里面
        for(int i = 0;i < res.size();i ++){
            for(int j = 0;j < res.get(0).size();j ++){
                ans[i][j] = res.get(i).get(j);
            }
        }
        return ans;
    }
    public void preOrders(TreeNode root){
        if(root==null){
            return ;
        }
        pre.add(root.val);
        preOrders(root.left);
        preOrders(root.right);
    }
    public void inOrders(TreeNode root){
        if(root==null){
            return ;
        }
        inOrders(root.left);
        in.add(root.val);
        inOrders(root.right);
    } 
    public void postOrders(TreeNode root){
        if(root==null){
            return ;
        }
        postOrders(root.left);
        postOrders(root.right);
        post.add(root.val);
    }

}

2023-3-12 15:51:19

NC90 设计getMin功能的栈

2023-3-12 15:52:22

NC90 包含min函数的栈

-3、设计思想:
>首先我们定义两个栈s1、s2,s1就用来存储给定的数据,s2用来维护栈的最小元素。
>然后你需要定义3个函数1)Push 入栈2Pop出栈 3)getMin()获取最小值
>Push:每次往s1加入一个元素后,需要判断s2的栈顶元素是否比它大,如果大就插入到s2
>Pop:每次弹出一个的时候,需要判断它和s2中的栈顶元素是否相等,如果相等s2还得出栈
>getMin:直接返回s2的栈顶元素就好了

import java.util.Stack;

public class Solution {

    // >首先我们定义两个栈s1、s2,s1就用来存储给定的数据,s2用来维护栈的最小元素。
    Stack<Integer> s1=new Stack<>();
    Stack<Integer> s2=new Stack<>();
    // >然后你需要定义3个函数1)Push 入栈2)Pop出栈 3)getMin()获取最小值
    // >Push:每次往s1加入一个元素后,需要判断s2的栈顶元素是否比它大,如果大就插入到s2
    public void push(int node) {
        s1.push(node);
        if(s2.isEmpty()||s2.peek()>=node){
            s2.push(node);
        }
    }
     // >Pop:每次弹出一个的时候,需要判断它和s2中的栈顶元素是否相等,如果相等s2还得出栈
    public void pop() {
        if(!s1.isEmpty()){
            
            if(s1.peek().equals(s2.peek())){
                s2.pop();
            }
            s1.pop();
        }
       
    }
   
    public int top() {
        return s1.peek();
    }
    // >getMin:直接返回s2的栈顶元素就好了
    public int min() {
        return s2.peek();
    }
}

2023-3-12 16:08:18

NC67连续子数组的最大和

已做

NC115栈和排序

-3、 设计思想:
>因为要满足字典序最大,所以第一个出栈的元素一定是n,所以我们需要定义一个n来控制元素的出栈顺序,为了满足字典序最大我们还得知道哪些元素己经入了栈,因为n-1有可能在n之前就入栈了,所以我们需要使用标记数组来指定哪些那些较大的数据入栈(因为这些数据可以提取出栈)
>那么我们就遍历一遍数据通过n和标记数组来控制出栈的顺序,如果数据遍历完,栈还没有空,我们只能将栈中元素全部弹出
import java.util.*;


public class Solution {
    /**
     * 栈排序
     * @param a int整型一维数组 描述入栈顺序
     * @return int整型一维数组
     */
    public int[] solve (int[] a) {
        // write code here
        Stack<Integer> s = new Stack<>();//定义一个栈用来存储数据
        int n = a.length;
        int []res = new int[n];//用来返回结果
        int cnt = 0;
        boolean []vis = new boolean[n+10];//用来标记哪个数字出现过
        for(int i =0;i < a.length;i ++){//遍历数组
            s.push(a[i]);//压入栈
            vis[a[i]] = true;//压入一个数就把对应的数字标记为true
            while(n>0&& vis[n]) n--;//检测现有栈中有多少个数出现了就是较大的哪些数出现了(从大到小)
            while(!s.empty() && n <= s.peek()){
                //然后将栈中>=n的元素出栈
                res[cnt ++] = s.pop();
            }
        }
        //如果栈没为空就按照栈中原样直接出栈
        while(!s.empty()){
            res[cnt++] = s.pop();
        }
        return res;
    }
}

2023-3-12 16:23:28

NC73数组中出现次数超过一半的数字

2023-3-12 16:24:14

NC73 数组中出现次数超过一半的数字

import java.util.*;
public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        HashMap<Integer,Integer> map=new HashMap<>();
        for(int i=0;i<array.length;i++){
            if(!map.containsKey(array[i])){
                map.put(array[i],1);
            }else{
                map.put(array[i],1+map.get(array[i]));
            }
        }
        for(int i=0;i<array.length;i++){
            if(map.get(array[i])>array.length/2){
                return(array[i]);
            }
        }
        return 0;
    }
}

2023-3-12 16:28:09

NC134股票(无限次交易)

2023-3-12 16:29:51

NC134 买卖股票的最好时机(二)

-3、 设计思想:
>因为是不限交易次数,所以我们可以将问题简化到只要有正收益就可以(即prices[i] - prices[i-1]0时就可以加入到我们最终的收益总和
>所以只需要遍历一遍数组,求一下prices[i] - prices[i-1]就解决了
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 计算最大收益
     * @param prices int整型一维数组 股票每一天的价格
     * @return int整型
     */
    public int maxProfit (int[] prices) {
        // write code here
        int res=0;
        for(int i=1;i<prices.length;i++){
            if(prices[i]-prices[i-1]>0){
                res+=prices[i]-prices[i-1];
            }
        }
        return res;
    }
}

NC114旋转字符串

2023-3-12 16:33:22

NC114 旋转字符串

import java.util.*;


public class Solution {
    /**
     * 旋转字符串
     * @param A string字符串 
     * @param B string字符串 
     * @return bool布尔型
     */
    public boolean solve (String A, String B) {
        // write code here
        /*如果字符串的长度都不相同就直接返回false
        如果长度相同,就让A字符串拼接自己然后在判断有没有B这个字符串
        */
        return A.length() == B.length() ? (A+A).contains(B) : false;
    }
}

最后

2023-3-12 16:35:42

这篇博客能写好的原因是:站在巨人的肩膀上

这篇博客要写好的目的是:做别人的肩膀

开源:为爱发电

学习:为我而行

  • 10
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

日星月云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值