几道Easy算法

1 两数之和

在这里插入图片描述
思路:使用一个HashMap集合存储每一个元素和对应下标。

	public int[] twoSum(int[] nums, int target) {
        HashMap<Integer,Integer> map=new HashMap<>();
        for(int i=0;i<nums.length;i++){
            //当前元素加上left后就等于目标值
            int left=target-nums[i];
            //如果left已经存在,说明存在这样的两个值,直接返回
            if(map.containsKey(left)){
                return new int[]{i,map.get(left)};
            }else{
                //不存在,就把当前元素和下标存入
                map.put(nums[i],i);
            }
        }
        return new int[2];
    }

2 有效的括号

在这里插入图片描述
思路:使用HashMap和栈解决。

public boolean isValid(String s) {
        HashMap<Character,Character> map=new HashMap<>();
        map.put(')','(');
        map.put('}','{');
        map.put(']','[');
        Stack<Character> stack=new Stack<>();
        for(int i=0;i<s.length();i++){
            //获取当前括号
            char c=s.charAt(i);
            //如果是右括号,判断栈顶是否为对应左括号
            if(map.containsKey(c)){
                if(!stack.isEmpty()&&stack.peek()==map.get(c)){
                    stack.pop();
                }else //不匹配直接返回false
                    return false;
            }else {//是左括号,存入栈
                stack.push(c);
            }
        }
        //如果栈空了,说明全部匹配成功
        return stack.isEmpty();
    }

3 合并两个有序链表

在这里插入图片描述
思路:while循环比较两个链表当前节点的值,将较小值节点作为新节点即可。

public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        //新链表表头
        ListNode pre=new ListNode(-1);
        //遍历指针
        ListNode node=pre;
        while(l1!=null&&l2!=null){
            if(l1.val<=l2.val){
                node.next=l1;
                l1=l1.next;
            }else{
                node.next=l2;
                l2=l2.next;
            }
            node=node.next;
        }
        //防止l1和l2有一个还没遍历完
        node.next=l2==null?l1:l2;
        return pre.next;
    }

4 最大子序和

在这里插入图片描述
思路:用一个临时遍历保持和,如果小于0就重新开始计算。

	public int maxSubArray(int[] nums) {
        if(nums.length==0)
            return 0;
        int max=nums[0];
        int temp=nums[0];
        for(int i=1;i<nums.length;i++){
            if(temp<0)
                temp=nums[i];
            else
                temp+=nums[i];
            //更新最大值
            if(temp>max)
                max=temp;
        }
        return max;
    }

5 爬楼梯

在这里插入图片描述
思路:经典的动态规划,比较简单,爬到i阶的方法=爬到i-1阶的方法+爬到i-2阶的方法。

	public int climbStairs(int n) {
        if(n==0||n==1||n==2)
            return n;
        int[] dp=new int[n+1];
        dp[0]=0;
        dp[1]=1;
        dp[2]=2;
        for(int i=3;i<n+1;i++){
            dp[i]=dp[i-1]+dp[i-2];
        }
        return dp[n];
    }

6 对称二叉树

在这里插入图片描述
思路:先判断根节点,如果不为空,再比较它的左右节点。

	public boolean isSymmetric(TreeNode root) {
        if(root==null)
            return true;
        return isMirror(root.left,root.right);
    }

    public boolean isMirror(TreeNode n1,TreeNode n2){
        //都为空,对称
        if(n1==null&&n2==null)
            return true;
        //一个为空,一个不为空,不对称
        if((n1==null&&n2!=null)||(n2==null&&n1!=null))
            return false;
        //值不相等,不对称
        if(n1.val!=n2.val)
            return false;
        //继续比较对称节点的关系
        return isMirror(n1.left,n2.right)&&isMirror(n1.right,n2.left);
    }

7 二叉树最大深度

在这里插入图片描述
思路:比较简单,求出左右子树的高度,取较大值。

	public int maxDepth(TreeNode root) {
        //空节点高度0
        if(root==null)
            return 0;
        //求左子树高度
        int hL=maxDepth(root.left);
        //求右子树高度
        int hR=maxDepth(root.right);
        return Math.max(hL,hR)+1;
    }

8 买卖股票的最佳时机

在这里插入图片描述
思路:动态规划,更新利益最大值和最低买入价。

	public int maxProfit(int[] prices) {
        if(prices.length==0)
            return 0;
        //保持最大利益
        int max=0;
        //保持最低买入价
        int min=prices[0];
        for(int i=1;i<prices.length;i++){
            if(max<prices[i]-min)
                max=prices[i]-min;
            min=Math.min(min,prices[i]);
        }
        return max;
	}    

9 只出现一次的数字

在这里插入图片描述

思路:利用异或的特点,两个相同数字异或为0,异或整个数组剩下的数字就是结果。

	public int singleNumber(int[] nums) {
        int num=nums[0];
        for(int i=1;i<nums.length;i++){
            num^=nums[i];
        }
        return num;
    }

10 环形链表

在这里插入图片描述
思路:利用快慢指针,如果相遇说明存在环,如果快指针遍历到null,说明不存在环。

	public boolean hasCycle(ListNode head) {
        ListNode slow=head;
        ListNode fast=head;
        while(fast!=null&&fast.next!=null){
            slow=slow.next;
            fast=fast.next.next;
            if(slow==fast)
                return true;
        }
        return false;
    }

11 最小栈

在这里插入图片描述
思路:使用2个栈,s1存放所有操作数,s2只操作最小数。

class MinStack {

    private Stack<Integer> s1=new Stack<>();
    private Stack<Integer> s2=new Stack<>();

    public MinStack() {

    }
    
    public void push(int x) {
        s1.push(x);
        //如果s2为空或者当前元素小于s2的栈顶元素
        if(s2.isEmpty()||x<=s2.peek())
            s2.push(x);
    }
    
    public void pop() {
        //如果s1和s2栈顶元素一样,s2也要出栈一个
        if(s1.peek().equals(s2.peek()))
            s2.pop();
        s1.pop();
    }
    
    public int top() {
        return s1.peek();
    }
    
    public int getMin() {
        return s2.peek();
    }
}

12 相交链表

在这里插入图片描述
思路:双指针遍历,如果到头就从另一条链表遍历,相等时返回节点。

	public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode p=headA;
        ListNode q=headB;
        while(p!=q){
            p=p!=null?p.next:headB;
            q=q!=null?q.next:headA;
        }
        return p;
    }

13 多数元素

在这里插入图片描述
思路:使用投票算法,如果当前数字和候选者值相同加1票,否则减1票,最终剩下的候选者就是最多的元素。

	public int majorityElement(int[] nums) {
        Integer leader=null;//初始时候选者不存在
        int count=0;//票数自然也为0
        for(int num:nums){
            //如果票数为0,新的数字成为候选者
            if(count==0)
                leader=num;
            //如果当前数字和候选者一样加1票,否则减1票
            count+=leader==num?1:-1;
        }
        return leader;
    }

14 打家劫舍

在这里插入图片描述
思路:动态规划,i房间可偷窃的最大值=(i-2房间可偷窃最大值+i房间的价值)和(i-1房间的最大值)中的较大值。

	public int rob(int[] nums) {
        if(nums.length==0)
            return 0;
        int[] dp=new int[nums.length+1];
        //初始化
        dp[0]=0;//防止i-2空指针异常,所以增加一个首元素
        dp[1]=nums[0];
        //动态规划
        for(int i=2;i<dp.length;i++){
            dp[i]=Math.max(dp[i-2]+nums[i-1],dp[i-1]);
        }
        return dp[dp.length-1];
    }

15 反转链表

在这里插入图片描述
思路:使用三个指针,分别存储前一个节点,当前节点,下一个节点。

	public ListNode reverseList(ListNode head) {
        ListNode pre=null;
        ListNode cur=head;
        ListNode next=null;
        while(cur!=null){
            next=cur.next;
            cur.next=pre;
            pre=cur;
            cur=next;
        }
        return pre;
    }

16 反转二叉树

在这里插入图片描述
思路:翻转左右子树,反向赋值即可。

	public TreeNode invertTree(TreeNode root) {
        if(root!=null){
            TreeNode left=invertTree(root.left);
            TreeNode right=invertTree(root.right);
            root.left=right;
            root.right=left;
        }
        return root;
    }

17 回文链表

在这里插入图片描述
思路:用ArrayList保持元素,比较前后是否一致。

	public boolean isPalindrome(ListNode head) {
        ArrayList<Integer> list=new ArrayList<>();
        while(head!=null){
            list.add(head.val);
            head=head.next;
        }
        for(int i=0;i<list.size()/2;i++){
            if(!list.get(i).equals(list.get(list.size()-1-i)))
                return false;
        }
        return true;
    }

18 移动零

在这里插入图片描述
思路:如果为0就将0计数器值加1,否则就按顺序填充一个位置,最后从末尾开始按0计数器个数填充0。

	public void moveZeroes(int[] nums) {
        //计算0元素的个数
        int count=0;
        //非0元素的存储下标
        int index=0;
        for(int i=0;i<nums.length;i++){
            if(nums[i]==0)
                count++;
            else
                nums[index++]=nums[i];
        }
        for(int i=nums.length-1;i>=nums.length-count;i--){
            nums[i]=0;
        }
    }

猜你喜欢

转载自blog.csdn.net/qq_41112238/article/details/105866360