初见

算法-leetcode刷题

2020-03-06  本文已影响0人  tylorsenna

[toc]

LeetCode.1 两数之和

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result = new int[2];
        // //双重循环  时间复杂度O(n²)
        // for(int i=0; i<nums.length; i++){
        //     for(int j=i+1; j<nums.length; j++){
        //         if(nums[i]+nums[j] == target){
        //             result[0] = i;
        //             result[1] = j;
        //             return result;
        //         }
        //     }
        // }

        //哈希表  O(n)
        HashMap<Integer,Integer> hashMap = new HashMap<Integer,Integer>();
        for(int i=0; i<nums.length; i++){
            if(hashMap.containsKey(nums[i])){
                result[0] = hashMap.get(nums[i]);
                result[1] = i;
            }
            //将数据存入  Key为补数——value为下标
            hashMap.put(target-nums[i], i);
        }
        return result;
    }
}

LeetCode.2 两数相加(大数、链表相加)

示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        int carry = 0;
        ListNode cursor = new ListNode(-1);
        ListNode result = cursor;
        while(l1 != null || l2 != null || carry>0){
            if(l1 != null){
                carry += l1.val;
                l1 = l1.next;
            }
            if(l2 != null){
                carry += l2.val;
                l2 = l2.next;
            }
            ListNode temp = new ListNode(carry%10);
            cursor.next = temp;
            cursor = temp;
            carry/=10;
        }
        return result.next;
    }
}

LeetCode.67 二进制求和

class Solution {
    public String addBinary(String a, String b) {
        // 太容易溢出,错误做法,位数需要满足数据类型。。。
        // int int_a = Integer.parseInt(a,2);
        // int int_b = Integer.parseInt(b,2);
        // int result = int_a + int_b;
        // return Integer.toBinaryString(result);
        //完美做法:类似链表加法
        StringBuffer sb = new StringBuffer();
        int carry = 0, i = a.length()-1, j = b.length()-1;
        while(i >= 0 || j >= 0 || carry != 0){
            if(i >= 0) carry += a.charAt(i--)-'0';
            if(j >= 0) carry += b.charAt(j--)-'0';
            sb.append(carry%2);
            carry /= 2;
        }
        return sb.reverse().toString();
    }
}

LeetCode.112 递归 路径之和Ⅰ(非递归用栈实现)

class Solution {
    public boolean hasPathSum(TreeNode root, int sum) {
        if(root == null){
            return false;
        }
        if(root.left == null && root.right == null){
            return sum - root.val == 0;
        }
        return hasPathSum(root.left, sum - root.val)||hasPathSum(root.right, sum - root.val);
    }
}

LeetCode.113 递归 路径之和Ⅱ

返回:[[5,4,11,2], [5,8,4,5]]

class Solution {
    List<List<Integer>> result = new ArrayList<>();
    List<Integer> inner = new ArrayList<>();
    public void union(TreeNode root, int sum){
        if(root == null){
            return;
        }
        sum -= root.val;
        inner.add(root.val);
        if(root.left == null && root.right == null){
            if(sum == 0){
                //因为List为引用类型,添加进result后修改还是会改变。所以返回的是拷贝(new 一个拷贝)
                result.add(new ArrayList(inner));
            }
            inner.remove(inner.size()-1);
            return;
        }
        if(root.left!=null) union(root.left, sum);
        if(root.right!=null) union(root.right, sum);
        inner.remove(inner.size()-1);
    }
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        union(root, sum);
        return result;
    }
}

LeetCode.120 动态规划or递归 三角形最小路径和

class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
        if(triangle == null || triangle.size() == 0){
            return 0;
        }
        //二维数组dp[][]
        // int[][] dp = new int[triangle.size()+1][triangle.size()+1];
        // for(int i = triangle.size()-1; i>=0; i--){
        //     List<Integer> curTri = triangle.get(i);
        //     for(int j = 0; j<curTri.size(); j++){
                   //dp[i][j]表示从顶点到第i+1层第j+1个节点的最小路径
        //         dp[i][j] = Math.min(dp[i+1][j], dp[i+1][j+1]) + curTri.get(j);
        //     }
        // }

        // // 只需要记录每一层的最小值即可 
        // int[] dp = new int[triangle.size()+1];
        // for(int i = triangle.size()-1; i>=0; i++){
        //     List<Integer> curTri = triangle.get(i);
        //     for(int j  = 0; j<curTri.size(); j++){
        //         //这里的dp[j] 使用的时候默认是上一层的,赋值之后变成当前层
        //         dp[j] = Math.min(dp[j], dp[j+1]) + curTri.get(j);
        //     }
        // }
        // return dp[0][0];
        
        //标准On
        int n = triangle.size();
        int[] dp = new int[n];
        for(int i = 0; i < n; i++) 
          dp[i] = triangle.get(n - 1).get(i);
        for(int i = n - 2; i >= 0; i--) {
          for(int j = 0; j <= i; j ++) {
            dp[j] = Math.min(dp[j], dp[j+1]) + triangle.get(i).get(j);
          }
        }    
        return dp[0];

        //递归法
        //return minimumTotalHelper(triangle, 0, 0, new int[triangle.size()][triangle.size()]); 
    }

    int minimumTotalHelper(List<List<Integer>> triangle, int row, int col, int[][] memo){
        if(memo[row][col] != 0) return memo[row][col];
        if(row == triangle.size()-1){
            return memo[row][col] = triangle.get(row).get(col);
        }
        int left = minimumTotalHelper(triangle, row+1, col, memo);
        int right = minimumTotalHelper(triangle, row+1, col+1, memo);
        return memo[row][col] = Math.min(left,right) + triangle.get(row).get(col);
    }
}

LeetCode.121 动态规划 买卖股票的最好时机1

    • 输入: [7,1,5,3,6,4]
    • 输出: 5
    • 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。注意利润不能是 7-1 = 6,因为卖出价格需要大于买入价格。
    • 输入: [7,6,4,3,1]
    • 输出: 0
    • 解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if(prices.size()<2) return 0;
        int min = prices[0];
        int profit = 0;
        for(int i=1; i<prices.size(); i++){
            profit = profit>prices[i]-min?profit:prices[i]-min;            
            min = min>prices[i]?prices[i]:min;
        }
        return profit;
    }
};

LeetCode.206 链表 反转链表

反转一个单链表。
示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
//迭代法:
public ListNode reverseList(ListNode head) {
    ListNode prev = null;
    ListNode curr = head;
    while (curr != null) {
        ListNode nextTemp = curr.next;
        curr.next = prev;
        prev = curr;
        curr = nextTemp;
    }
    return prev;
}
//递归:
public ListNode reverseList(ListNode head) {
    if (head == null || head.next == null) return head;
    ListNode p = reverseList(head.next);
    head.next.next = head;
    head.next = null;
    return p;
}

LeetCode.225 队列实现栈

class MyStack {

    Queue<Integer> queue;

    /** Initialize your data structure here. */
    public MyStack() {
        queue = new LinkedList<Integer>();
    }
    
    /** Push element x onto stack. */
    public void push(int x) {
        int size = queue.size();
        queue.add(x);
        for( ; size>0; size--){
            queue.add(queue.remove());
        }
    }
    
    /** Removes the element on top of the stack and returns that element. */
    public int pop() {
        return queue.remove();
    }
    
    /** Get the top element. */
    public int top() {
        return queue.peek();
    }
    
    /** Returns whether the stack is empty. */
    public boolean empty() {
        if(queue.isEmpty()){
            return true;
        }else{
            return false;
        }
    }
}

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack obj = new MyStack();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.top();
 * boolean param_4 = obj.empty();
 */

LeetCode 面试题57-II 和为target的连续正数序列

示例 1:
输入:target = 9
输出:[[2,3,4],[4,5]]
示例 2:
输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]
class Solution {
    public int[][] findContinuousSequence(int target) {
        List<int[]> result = new ArrayList<>();
        //target肯定是奇数(由两个连续的数相加(奇数加偶数等于奇数))
        //最大的连续子序列肯定是target的一半的上界加下界(target = mid+mid+1)
        int mid = target/2;
        //1.滑动窗口暴力法
        /*
        for(int i=1; i<=mid; i++){
            int sum = 0;
            int j=i;
            while(sum < target){
                sum += j++;
            }
            if(sum == target){
                int[] temp = new int[j-i];
                for(int k=0; k<j-i; k++){
                    temp[k] = k+i;
                }
                result.add(temp);
            }
        }*/
        //双指针优化
        for(int l=1,r=2; l<r; ){
            int sum = (l + r) * (r - l + 1) / 2;
            if (sum == target){
                int[] temp = new int[r-l+1];
                for (int i = l; i <= r; ++i) temp[i-l] = i;
                result.add(temp);
                l++;
            }
            else if (sum < target) r++;
            else l++;

        }
        return result.toArray(new int[result.size()][]);
    }
}

LeetCode.994 腐烂的橘子

在给定的网格中,每个单元格可以有以下三个值之一:
值0代表空单元格;
值1代表新鲜橘子;
值2代表腐烂的橘子。
每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂。

返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回-1。
示例 1:
输入:[[2,1,1],[1,1,0],[0,1,1]]
输出:4
示例 2:
输入:[[2,1,1],[0,1,1],[1,0,1]]
输出:-1
解释:左下角的橘子(第 2 行, 第 0 列)永远不会腐烂,因为腐烂只会发生在 4 个正向上。
示例 3:
输入:[[0,2]]
输出:0
解释:因为 0 分钟时已经没有新鲜橘子了,所以答案就是 0 。
提示:
1 <= grid.length <= 10
1 <= grid[0].length <= 10
grid[i][j] 仅为0、1或2

class Solution {
    int[][] dir = { {-1,0},{1,0},{0,-1},{0,1} };
    class Node{
        int x;
        int y;
        int minute;
        Node(int x, int y, int minute){
            this.x = x;
            this.y = y;
            this.minute = minute;
        }
    }
    public int orangesRotting(int[][] grid) {
        int rows = grid.length;
        int clunms = grid[0].length;
        int minute = 0;
        Queue<Node> queue = new LinkedList<>();

        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < clunms; j++)
            if (grid[i][j] == 2)
                queue.add(new Node(i, j, minute));
        }
        while (!queue.isEmpty()) {
            Node node = queue.poll();
            minute = node.minute;
            for (int k = 0; k < 4; k++) {   //一个腐烂,四周受害
                int newX = node.x + dir[k][0];
                int newY = node.y + dir[k][1];
                if (newX >= 0 && newX < rows && newY >= 0 && newY < clunms && grid[newX][newY] == 1) {
                    grid[newX][newY] = 2;  //标记腐烂
                    queue.add(new Node(newX, newY, node.minute + 1)); //腐烂周期+1
                }
            }
        }
        //check for fresh oranges
        for(int[] row : grid) {
            for (int i : row)
                if (i == 1) return -1;
        }
        return minute;
    }
}
上一篇 下一篇

猜你喜欢

热点阅读