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

    二维数组初始化:

    int[][] a = {{1,3},{2,6},{8,10},{15,18}};


    120. Triangle

    给出一个三角形(数据数组),找出从上往下的最小路径和。每一步只能移动到下一行中的相邻结点上。

    解法,自底向上

    The idea is simple.

    1.  Go from bottom to top.

    2.  We start form the row above the bottom row [size()-2].

    3.  Each number add the smaller number of two numbers that below it.

    4.  And finally we get to the top we the smallest sum.

      public int minimumTotal(List<List<Integer>> triangle) {
            for(int i = triangle.size() - 2; i >= 0; i--)
                for(int j = 0; j <= i; j++)
                    triangle.get(i).set(j, triangle.get(i).get(j) + Math.min(triangle.get(i + 1).get(j), triangle.get(i + 1).get(j + 1)));
            return triangle.get(0).get(0);
        }

    Boyer-Moore majority vote algorithm(摩尔投票算法)

    简介

    Boyer-Moore majority vote algorithm(摩尔投票算法)是一种在线性时间O(n)和空间复杂度的情况下,在一个元素序列中查找包含最多的元素。它是以Robert S.Boyer和J Strother Moore命名的,1981年发明的,是一种典型的流算法(streaming algorithm)。

    在它最简单的形式就是,查找最多的元素,也就是在输入中重复出现超过一半以上(n/2)的元素。如果序列中没有最多的元素,算法不能检测到正确结果,将输出其中的一个元素之一。

    当元素重复的次数比较小的时候,对于流算法不能在小于线性空间的情况下查找频率最高的元素。

    算法描述

    算法在局部变量中定义一个序列元素(m)和一个计数器(i),初始化的情况下计数器为0. 算法依次扫描序列中的元素,当处理元素x的时候,如果计数器为0,那么将x赋值给m,然后将计数器(i)设置为1,如果计数器不为0,那么将序列元素m和x比较,如果相等,那么计数器加1,如果不等,那么计数器减1。处理之后,最后存储的序列元素(m),就是这个序列中最多的元素。

    如果不确定是否存储的元素m是最多的元素,还可以进行第二遍扫描判断是否为最多的元素。

    perudocode

    • Initialize an element m and a counter i with i = 0
    • For each element x of the input sequence:
      • if i = 0, then assign m = x and i = 1
      • else if m = x, then assign i = i + 1
      • else assign i = i − 1
    • Return m

    问题1:数组中存在元素出现次数大于 ⌊ n/2 ⌋ ,求该元素

    上面方法即可

    问题2:数组中是否存在元素出现次数大于 ⌊ n/2 ⌋ 

    用上面找到的摩尔投票算法,第一遍扫描输出一个存储的元素,然后还需要进行第二遍扫描来判断元素在序列中是否确实超过n/2了。 因为一个元素超过一半,最后肯定会留下,但是最后留下的不一定超过一半,所以要扫描第二遍。

    229. Majority Element II

    求出现次数大于n/3的众数,而且限定了时间和空间复杂度,那么就不能排序,也不能使用哈希表,这么苛刻的限制条件只有一种方法能解了,那就是摩尔投票法 Moore Voting

    我们先考虑可能会有多少个众数,经过举了很多例子分析得出,任意一个数组出现次数大于n/3的众数最多有两个

    我们使用投票法的核心是找出两个候选众数进行投票,需要两遍遍历,第一遍历找出两个候选众数,第二遍遍历重新投票验证这两个候选众数是否为众数即可,选候选众数方法和前面那篇Majority Element 求众数一样,由于之前那题题目中限定了一定会有众数存在,故而省略了验证候选众数的步骤,这道题却没有这种限定,即满足要求的众数可能不存在,所以要有验证。

    public List<Integer> majorityElement(int[] nums) {
        if (nums == null || nums.length == 0)
            return new ArrayList<Integer>();
        List<Integer> result = new ArrayList<Integer>();
        int number1 = nums[0], number2 = nums[0], count1 = 0, count2 = 0, len = nums.length;
        for (int i = 0; i < len; i++) {
            if (nums[i] == number1)
                count1++;
            else if (nums[i] == number2)
                count2++;
            else if (count1 == 0) {
                number1 = nums[i];
                count1 = 1;
            } else if (count2 == 0) {
                number2 = nums[i];
                count2 = 1;
            } else {
                count1--;//不属于这两个,都要减一
                count2--;
            }
        }
        count1 = 0;
        count2 = 0;
        for (int i = 0; i < len; i++) {
            if (nums[i] == number1)
                count1++;
            else if (nums[i] == number2)
                count2++;
        }
        if (count1 > len / 3)
            result.add(number1);
        if (count2 > len / 3)
            result.add(number2);
        return result;
    }

    旋转数组的最小数字

    采用二分法解答这个问题,
    mid = low + (high - low)/2
    需要考虑三种情况:
    (1)array[mid] > array[high]:
    出现这种情况的array类似[3,4,5,6,0,1,2],此时最小数字一定在mid的右边。
    low = mid + 1
    (2)array[mid] == array[high]:
    出现这种情况的array类似 [1,0,1,1,1] 或者[1,1,1,0,1],此时最小数字不好判断在mid左边
    还是右边,这时只好一个一个试 ,
    high = high - 1
    (3)array[mid] < array[high]:
    出现这种情况的array类似[2,2,3,4,5,6,6],此时最小数字一定就是array[mid]或者在mid的左
    边。因为右边必然都是递增的。
    high = mid
    注意这里有个坑:如果待查询的范围最后只剩两个数,那么mid 一定会指向下标靠前的数字
    比如 array = [4,6]
    array[low] = 4 ;array[mid] = 4 ; array[high] = 6 ;
    如果high = mid - 1,就会产生错误, 因此high = mid
    但情形(1)中low = mid + 1就不会错误

    import java.util.ArrayList;
    public class Solution {
        public int minNumberInRotateArray(int [] array) {
            int low = 0 ; int high = array.length - 1;   
            while(low < high){
                int mid = low + (high - low) / 2;        
                if(array[mid] > array[high]){
                    low = mid + 1;
                }else if(array[mid] == array[high]){
                    high = high - 1;
                }else{
                    high = mid;
                }   
            }
            return array[low];
        }
    }
    //旋转二分查找目标值
        public int search(int[] nums, int target) {
            int length=nums.length;
            if(length<=0) return -1;
            int low=0;
            int high=length-1;
            int mid=-1;
            while (low<=high){
                mid=(low+high)/2;
                if(target==nums[mid]) {
                    return mid;
                }else {
                    if(nums[mid]<nums[high]){
                        if(nums[mid]<target&&nums[high]>=target) low=mid+1;
                        else high=mid-1;
                    }else {
                        if(nums[low]<=target&&nums[mid]>target) high=mid-1;
                        else low=mid+1;
                    }
                }
            }
            return -1;
        }
    }

    任务列表(360公司2017春招真题)

    现在现在有一台机器,这台机器可以接收两种形式任务:(1)任务列表,任务列表里面有N个任务,对于第i个任务,机器在Ti时间开始执行,并在1个单位时间内做完。(2)临时任务,机器可以在任意时间接收一个临时任务,但任务列表里面的任务优先级要高于临时任务,也就是说当机器空闲的时候才会执行临时任务。

    现在机器已经接收一个任务列表。接下来会有M个临时任务,我们想知道每个临时任务何时被执行。为了简化问题我们可以认为这M个临时任务是独立无关即任务是可以同时执行的,互不影响的。

    输入
    输入数据有多组,每组数据第一行包括两个整数N和M(1<=N, M<=10^5)。
    接下来一行有N个不同数字T1,T2,T3.....TN(1<=T1
    接下来又M行,每行一个数字Qi(1<=Qi<=10^9),表示第i个临时任务的的接收时间。
    输出
    对于每个临时任务,输出它被执行的时间。
    样例输入
    5 6
    1 2 3 5 6
    3
    2
    1
    4
    5
    6
    样例输出
    4
    4
    4
    4
    7

    7

    将不能执行的时间标出来 对于每个临时任务往后找出一个可以执行的时间

        public static void main(String[] args) {
    
            Scanner cin = new Scanner(System.in);
            int n = cin.nextInt();
            int m = cin.nextInt();
            int[] gap = new int[100000];
            for (int i = 0; i < n; i++) {
                int temp = cin.nextInt();
                gap[temp] = 1;
            }
            int[] result = new int[m];
            for (int i = 0; i < m; i++) {
                int temp = cin.nextInt();
    
                for (int j = temp; j < gap.length; j++) {
                    if (gap[j] != 1) {
                        result[i] = j;
                        break;
                    }
                }
    
            }
    
            for (int i = 0; i < result.length; i++) {
                System.out.println(result[i]);
            }
    
        }

    56. Merge Intervals

    先把第一个区间加入结果集,在循环中如果更新了第一个区间的max interval[1],result的第一个interval也会随之更新

    public int[][] merge(int[][] intervals) {
            if (intervals.length <= 1)
                return intervals;
    
            // Sort by ascending starting point
            Arrays.sort(intervals, (i1, i2) -> Integer.compare(i1[0], i2[0]));
    
            List<int[]> result = new ArrayList<>();
            int[] newInterval = intervals[0];
            result.add(newInterval);
            for (int[] interval : intervals) {
                if (interval[0] <= newInterval[1]) // Overlapping intervals, move the end if needed
                    newInterval[1] = Math.max(newInterval[1], interval[1]);
                else {                             // Disjoint intervals, add the new interval to the list
                    newInterval = interval;
                    result.add(newInterval);
                }
            }
    
            return result.toArray(new int[result.size()][]);
        }
  • 相关阅读:
    如何输出高精度时间差
    GetThreadTimes获取其它线程cpu时间
    12-Python基础之类与面向对象
    10-Python函数之递归
    09-Python基础之内置函数与匿名函数
    08-Python基础之迭代器与生成器
    07-Python基础之装饰器
    06-Python基础之函数进阶(嵌套,作用域)
    05-Python基础之函数基础
    04-Python基础之文件操作基础
  • 原文地址:https://www.cnblogs.com/34fj/p/9310620.html
Copyright © 2011-2022 走看看