zoukankan      html  css  js  c++  java
  • leetcode: 数组

    1. longest-consecutive-sequence

    Given an unsorted array of integers, find the length of the longest consecutive elements sequence.

    For example,
    Given[100, 4, 200, 1, 3, 2],
    The longest consecutive elements sequence is[1, 2, 3, 4]. Return its length:4.

    Your algorithm should run in O(n) complexity.

    给定一个整形数组,求出最长的连续序列。例如数组[100,4,200,1,3,2],最长的连续序列长度为[1,2,3,4],长度为4。要求时间复杂度为O(n)。

    排序的话至少要O(nlgn) 的复杂度。O(n)的复杂度,目前只找到了使用hash来解决的方案,add, remove, contains 等方法的复杂度都是 O(1),因此两次遍历的操作复杂度为 O(n)。

    public static int longestConsecutive(int[] num) {
        // if array is empty, return 0
        if (num.length == 0) {
            return 0;
        }
     
        Set<Integer> set = new HashSet<Integer>();
        int max = 1;
     
        for (int e : num)
            set.add(e);
     
        for (int e : num) {
            int left = e - 1;
            int right = e + 1;
            int count = 1;
     
            while (set.contains(left)) {
                count++;
                set.remove(left);
                left--;
            }
     
            while (set.contains(right)) {
                count++;
                set.remove(right);
                right++;
            }
     
            max = Math.max(count, max);
        }
     
        return max;
    }
    View Code

    2. surrounded-regions

    Given a 2D board containing'X'and'O', capture all regions surrounded by'X'.

    A region is captured by flipping all'O's into'X's in that surrounded region .

    For example,

    X X X X
    X O O X
    X X O X
    X O X X

    After running your function, the board should be:

    X X X X
    X X X X
    X X X X
    X O X X

    典型的BFS题目。遍历每个字符,如果是“O”,则从当前字符开始BFS遍历,如果周围也是“O”则加入当前遍历的队列,知道遍历完所有相邻的“O”,于此同时,判断每个O是否是被包围的,只有由一个O是没有被包围的,则当前遍历的O的集合都是没有被包围的,因为这些O都是相连的。

    当然,此题使用DFS也可以,只是测试数据过大,提交时StackOverFlow.

    1)BFS 广度优先搜索

    public class Solution {
        // use a queue to do BFS
        private Queue<Integer> queue = new LinkedList<Integer>();
     
        public void solve(char[][] board) {
            if (board == null || board.length == 0)
                return;
     
            int m = board.length;
            int n = board[0].length;
     
            // merge O's on left & right boarder
            for (int i = 0; i < m; i++) {
                if (board[i][0] == 'O') {
                    bfs(board, i, 0);
                }
     
                if (board[i][n - 1] == 'O') {
                    bfs(board, i, n - 1);
                }
            }
     
            // merge O's on top & bottom boarder
            for (int j = 0; j < n; j++) {
                if (board[0][j] == 'O') {
                    bfs(board, 0, j);
                }
     
                if (board[m - 1][j] == 'O') {
                    bfs(board, m - 1, j);
                }
            }
     
            // process the board
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < n; j++) {
                    if (board[i][j] == 'O') {
                        board[i][j] = 'X';
                    } else if (board[i][j] == '#') {
                        board[i][j] = 'O';
                    }
                }
            }
        }
     
        private void bfs(char[][] board, int i, int j) {
            int n = board[0].length;
     
            // fill current first and then its neighbors
            fillCell(board, i, j);
     
            while (!queue.isEmpty()) {
                int cur = queue.poll();
                int x = cur / n;
                int y = cur % n;
     
                fillCell(board, x - 1, y);
                fillCell(board, x + 1, y);
                fillCell(board, x, y - 1);
                fillCell(board, x, y + 1);
            }
        }
     
        private void fillCell(char[][] board, int i, int j) {
            int m = board.length;
            int n = board[0].length;
            if (i < 0 || i >= m || j < 0 || j >= n || board[i][j] != 'O')
                return;
     
            // add current cell is queue & then process its neighbors in bfs
            queue.offer(i * n + j);
            board[i][j] = '#';    // 用#标识要保留的O
        }
    }
    View Code

    2)DFS深度优先搜索

    public void solve(char[][] board) {
        if(board == null || board.length==0) 
            return;
     
        int m = board.length;
        int n = board[0].length;
     
        //merge O's on left & right boarder
        for(int i=0;i<m;i++){
            if(board[i][0] == 'O'){
                merge(board, i, 0);
            }
     
            if(board[i][n-1] == 'O'){
                merge(board, i,n-1);
            }
        }
     
        //merge O's on top & bottom boarder
        for(int j=0; j<n; j++){
             if(board[0][j] == 'O'){
                merge(board, 0,j);
            }
     
            if(board[m-1][j] == 'O'){
                merge(board, m-1,j);
            }
        }
     
        //process the board
        for(int i=0;i<m;i++){
            for(int j=0; j<n; j++){
                if(board[i][j] == 'O'){
                    board[i][j] = 'X';
                }else if(board[i][j] == '#'){
                    board[i][j] = 'O';
                }
            }
        }
    }
     
    public void merge(char[][] board, int i, int j){
        if(i<0 || i>=board.length || j<0 || j>=board[0].length) 
            return;
     
        if(board[i][j] != 'O')
            return;
     
        board[i][j] = '#';
     
       // 递归实现深度优先搜索
        merge(board, i-1, j);
        merge(board, i+1, j);
        merge(board, i, j-1);
        merge(board, i, j+1);
    }
    View Code

    3. Best Time to Buy and Sell Stock  I II III 

    3.1 Best Time to Buy and Sell Stock  I 

    Description: Say you have an array for which the ith element is the price of a given stock on day i. If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find
    the maximum profit.

    题意:用一个数组表示股票每天的价格,数组的第i个数表示股票在第i天的价格。 如果只允许进行一次交易,也就是说只允许买一支股票并卖掉,求最大的收益。

    分析:动态规划法。从前向后遍历数组,记录当前出现过的最低价格,作为买入价格,并计算以当天价格出售的收益,作为可能的最大收益,整个遍历过程中,出现过的最大收益就是所求。

    代码:O(n)时间,O(1)空间。

    public class Solution {
        public int maxProfit(int[] prices) {
            if (prices.length < 2) return 0;
            
            int maxProfit = 0;
            int curMin = prices[0];
            
            for (int i = 1; i < prices.length; i++) {
                curMin = Math.min(curMin, prices[i]);
                maxProfit = Math.max(maxProfit, prices[i] - curMin);
            }
            
            return maxProfit;
        }
    }
    View Code

    3.2 Best Time to Buy and Sell Stock  II

    Description: Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

    题目:用一个数组表示股票每天的价格,数组的第i个数表示股票在第i天的价格。  交易次数不限,   但一次只能交易一支股票,也就是说手上最多只能持有一支股票,求最大收益。

    分析:贪心法。从前向后遍历数组,只要当天的价格高于前一天的价格,就算入收益。

    代码:时间O(n),空间O(1)。

    public class Solution {
        public int maxProfit(int[] prices) {
            if (prices.length < 2) return 0;
            
            int maxProfit = 0;
            for (int i = 1; i < prices.length; i++) {
                int diff = prices[i] - prices[i - 1];
                if (diff > 0) {
                    maxProfit += diff;
                }
            }
            
            return maxProfit;
        }
    }
    View Code

    3.3 Best Time to Buy and Sell Stock  III 

    Description: Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete at most two transactions. Note: You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

    题意:用一个数组表示股票每天的价格,数组的第i个数表示股票在第i天的价格。最多交易两次,手上最多只能持有一支股票,求最大收益。

    分析:动态规划法。以第i天为分界线,计算第i天之前进行一次交易的最大收益preProfit[i],和第i天之后进行一次交易的最大收益postProfit[i],最后遍历一遍,max{preProfit[i] + postProfit[i]} (0≤i≤n-1)就是最大收益。第i天之前和第i天之后进行一次的最大收益求法同Best Time to Buy and Sell Stock I。

    代码:时间O(n),空间O(n)。

    public class Solution {
        public int maxProfit(int[] prices) {
            if (prices.length < 2) return 0;
            
            int n = prices.length;
            int[] preProfit = new int[n];
            int[] postProfit = new int[n];
            
            int curMin = prices[0];
            for (int i = 1; i < n; i++) {
                curMin = Math.min(curMin, prices[i]);
                preProfit[i] = Math.max(preProfit[i - 1], prices[i] - curMin);
            }
            
            int curMax = prices[n - 1];
            for (int i = n - 2; i >= 0; i--) {
                curMax = Math.max(curMax, prices[i]);
                postProfit[i] = Math.max(postProfit[i + 1], curMax - prices[i]);
            }
            
            int maxProfit = 0;
            for (int i = 0; i < n; i++) {
                maxProfit = Math.max(maxProfit, preProfit[i] + postProfit[i]);
            }
            
            return  maxProfit;
        }
    }
    View Code

    4. convert-sorted-array-to-binary-search-tree

    Given an array where elements are sorted in ascending order, convert it to a height balanced BST.

    从给定的有序数组转成一个平衡二叉树(左子树<根结点<右子树)

    /**
     * Definition for binary tree
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    
    public class Solution {
        private TreeNode buildTree(int[] num, int start, int end) {
            if (start > end) {
                return null;
            }
    
            TreeNode node = new TreeNode(num[(start + end) / 2]);
            node.left = buildTree(num, start, (start + end) / 2 - 1);
            node.right = buildTree(num, (start + end) / 2 + 1, end);
            return node;
        }
    
        public TreeNode sortedArrayToBST(int[] num) {
            if (num == null) {
                return null;
            }
            return buildTree(num, 0, num.length - 1);
        }
    }
    View Code

    5. plus-one

      Given a non-negative number represented as an array of digits, plus one to the number. 
      The digits are stored such that the most significant digit is at the head of the list. 

      给定一个用数组表示的一个数,对它进行加一操作。 
      每一个数位都存储在数组的一个位置上。数组下标从大到小表示数位从低位到高位。 

      直接求解,设置一个进位标志carry,初值为1,表示加1,从最低位开始tmp = a[x] + carry, 
    a[x] = tmp%10,carry = tmp/10,如果carry不为0对下一位再进行操作,直到所有的数位处理完或者carray为0就退出,如果最后还有carray不为0说明整个数组要扩展一个数位。 

    public class Solution{
        public int[] plusOne(int[] digits) {
        int len = digits.length;
        
        boolean flag = true; // 进位标记
     
        for (int i = len - 1; i >= 0; i--) {
            if (flag) {
                if (digits[i] == 9) {
                    digits[i] = 0;
                } else {
                    digits[i] = digits[i] + 1;
                    flag = false;
                }
     
                if (i == 0 && digits[i] == 0) {
                    int[] y = new int[len + 1];
                    y[0] = 1;
                    for (int j = 1; j <= len; j++) {
                        y[j] = digits[j - 1];
                    }
                    digits = y;
                }
            }
        }
     
        return digits;
    }
    }
    View Code

    6. search-a-2d-matrix

    Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties

    • Integers in each row are sorted from left to right.
    • The first integer of each row is greater than the last integer of the previous row.

    For example,

    Consider the following matrix:

    [
      [1,   3,  5,  7],
      [10, 11, 16, 20],
      [23, 30, 34, 50]
    ]
    

    Given target =3, return true.

    解法一:

    从右上到左下进行搜索。时间复杂度 O(m + n)

    解法二:

    如果把第0行,第1行,第i行...第i+1行依次连接起来,使得2D数组被还原为1D数组,那么显然这个1D数组就被转化成为了一个排好序的数组。接下来普通的二分搜索就OK了。  时间复杂度lg(m * n) = lg(m) + lg(n)

    // 二分法
    public class Solution {
        public boolean searchMatrix(int[][] matrix, int target) {
            if(matrix==null || matrix.length==0 || matrix[0].length==0) 
                return false;
     
            int m = matrix.length;
            int n = matrix[0].length;
     
            int start = 0;
            int end = m*n-1;
     
            while(start<=end){
                int mid=(start+end)/2;
                int midX=mid/n;
                int midY=mid%n;
     
                if(matrix[midX][midY]==target) 
                    return true;
     
                if(matrix[midX][midY]<target){
                    start=mid+1;
                }else{
                    end=mid-1;
                }
            }
     
            return false;
        }
    }
    View Code

    7. rotate image

    You are given an n x n 2D matrix representing an image.

    Rotate the image by 90 degrees (clockwise).

    Follow up:
    Could you do this in-place?

     二维数组a[n][n] 顺时针旋转90度,  规律 :a[i][j]=a[n-1-j][i]

    public class Solution {
        public void rotate(int[][] matrix) {
            if(matrix == null || matrix.length==0)
                return ;
     
            int m = matrix.length;
     
            int[][] result = new int[m][m];
     
            for(int i=0; i<m; i++){
                for(int j=0; j<m; j++){
                    result[j][m-1-i] = matrix[i][j];
                }
            } 
     
           for(int i=0; i<m; i++){
                for(int j=0; j<m; j++){
                    matrix[i][j] = result[i][j];
                }
            } 
        }
    }
    View Code

    8. spiral-matrix

    Given a matrix of m x n elements (mrows, n columns), return all elements of the matrix in spiral order.

    For example,
    Given the following matrix:

    [
     [ 1, 2, 3 ],
     [ 4, 5, 6 ],
     [ 7, 8, 9 ]
    ]
    

    You should return[1,2,3,6,9,8,7,4,5].

    特殊情况: 只有一行或一列;  其他情况,从左到右,从上到下,从右到坐,从下到上,完成一轮,矩阵的长宽缩减2

    public class Solution {
        public ArrayList<Integer> spiralOrder(int[][] matrix) {
            ArrayList<Integer> result = new ArrayList<Integer>();
     
            if(matrix == null || matrix.length == 0) return result;
     
            int m = matrix.length;
            int n = matrix[0].length;
     
            int x=0; 
            int y=0;
     
            while(m>0 && n>0){
     
                //if one row/column left, no circle can be formed
                if(m==1){
                    for(int i=0; i<n; i++){
                        result.add(matrix[x][y++]);
                    }
                    break;
                }else if(n==1){
                    for(int i=0; i<m; i++){
                        result.add(matrix[x++][y]);
                    }
                    break;
                }
     
                //below, process a circle
     
                //top - move right
                for(int i=0;i<n-1;i++){
                    result.add(matrix[x][y++]);
                }
     
                //right - move down
                for(int i=0;i<m-1;i++){
                    result.add(matrix[x++][y]);
                }
     
                //bottom - move left
                for(int i=0;i<n-1;i++){
                    result.add(matrix[x][y--]);
                }
     
                //left - move up
                for(int i=0;i<m-1;i++){
                    result.add(matrix[x--][y]);
                }
     
                x++;
                y++;
                m=m-2;
                n=n-2;
            }
     
            return result;
        }
    }
    View Code

    9. merge-intervals

    Given a collection of intervals, merge all overlapping intervals.

    For example,
    Given[1,3],[2,6],[8,10],[15,18],
    return[1,6],[8,10],[15,18]

    给定一个区间集合,合并有重叠的区间

     先对区间排序,按开始点进行排序,再一个个进行合并;如果结果集合为空或者当前interval与结果集合中最后一个interval不重叠,那么就直接将当前interval加入到结果中;如果发生了重叠,那么修改结果集合中的最后一个interval的右端点(改为当前interval的右端点或不修改)

    /**
     * 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 List<Interval> merge(List<Interval> intervals) {
        List<Interval> list = new ArrayList<Interval>();
        Comparator<Interval> comparator = new Comparator<Interval>() {
            @Override
            public int compare(Interval o1, Interval o2) {
                if (o1.start == o2.start)
                    return o1.end - o2.end;
                return o1.start - o2.start;
            }
        };
        Collections.sort(intervals, comparator);
        for (Interval interval : intervals)
            if (list.size() == 0 || list.get(list.size() - 1).end < interval.start)
                list.add(new Interval(interval.start, interval.end));
            else
                list.get(list.size() - 1).end = Math.max(interval.end, list.get(list.size() - 1).end);
        return list;
    }
     
     
    View Code

    10. Merge Sorted Array

    Given two sorted integer arrays A and B, merge B into A as one sorted array.

    Note:
    You may assume that A has enough space to hold additional elements from B. The number of elements initialized in A and B are m and n respectively.

    考虑从后往前比较,这样就不会产生需要数据后移的问题了;同时考虑B数组还有剩余的情况。时间复杂度O(n+m)

    public class Solution {
        public void merge(int A[], int m, int B[], int n) {
     
            while(m > 0 && n > 0){
                if(A[m-1] > B[n-1]){
                    A[m+n-1] = A[m-1];
                    m--;
                }else{
                    A[m+n-1] = B[n-1];
                    n--;
                }
            }
     
            while(n > 0){
                A[m+n-1] = B[n-1];
                n--;
            }
        }
    }
    View Code
    public void merge(int A[], int m, int B[], int n) {
        int i = m - 1;
        int j = n - 1;
        int k = m + n - 1;
     
        while (k >= 0) {
            if (j < 0 || (i >= 0 && A[i] > B[j]))
                A[k--] = A[i--];
            else
                A[k--] = B[j--];
        }
    }
    View Code

    11. 3sum-closest

    Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

        For example, given array S = {-1 2 1 -4}, and target = 1.
    
        The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

    先固定一个数,剩下的用2sum方法解决即可,采用两个指针从前后方向,时间复杂度O(n^2)

    public int threeSumClosest(int[] nums, int target) {
        int min = Integer.MAX_VALUE;
        int result = 0;
     
        Arrays.sort(nums);
     
        for (int i = 0; i < nums.length; i++) {
            int j = i + 1;
            int k = nums.length - 1;
            while (j < k) {
                int sum = nums[i] + nums[j] + nums[k];
                int diff = Math.abs(sum - target);
     
                if(diff == 0) return sum;
     
                if (diff < min) {
                    min = diff;
                    result = sum;
                }
                if (sum <= target) {
                    j++;
                } else {
                    k--;
                }
            }
        }
     
        return result;
    }
    View Code

     

    12. remove element

    Given an array and a value, remove all instances of that value in place and return the new length.

    The order of elements can be changed. It doesn't matter what you leave beyond the new length.

    返回所有删除指定元素的数组

    1)把原数组A的元素拷贝到新的数组中,A可以当做新的数组

    public class Solution {  
        public int removeElement(int[] A, int elem) {  
            int newIndex = 0;  
            for (int oldIndex = 0; oldIndex < A.length; ++oldIndex) {  
                if (A[oldIndex] != elem) {  
                    A[newIndex++] = A[oldIndex];  
                }   
                oldIndex++;
            }  
            return newIndex;  
        }  
    }  
    View Code

    2)把不需要的元素放在原数组的尾部

    public class Solution {  
        public int removeElement(int[] A, int elem) {  
            if (A.length ==0) return A.length;  
            //if (A.lenth == 1 && A[0] == elem) return 0;  
            //if (A.lenth == 1 && A[0] != elem) return 1;  
            int i = 0, j = A.length - 1;  
            //while (i < j) {  
            while (i <= j) {  
                if (A[i] == elem) {  
                    int tmp = A[i];  
                    A[i] = A[j];  
                    A[j] = tmp;  
                    --j;  
                } else {  
                    ++i;  
                }  
            }  
            //return j; 因为while (i<=j)才结束,而不是while (i < j)才结束,所以这里返回j+1  
            return j + 1;  
        }  
    }  
    View Code
  • 相关阅读:
    汉语-词语:慧根
    汉语-词语:悟性
    汉语-汉字:耑
    汉语-汉字:羣
    汉语-词语:觉察
    汉语-词语:醒悟
    汉语-词语:觉悟
    Redhat 5禁止IPv6
    从缓存行出发理解volatile变量、伪共享False sharing、disruptor
    【故障处理141119】一次数据库不繁忙时一条sql语句2个运行计划导致业务超时的故障处理
  • 原文地址:https://www.cnblogs.com/zxqstrong/p/5358966.html
Copyright © 2011-2022 走看看