java leetcodetop100 (3,4) longest continuous sequence, moving zero

top3 longest continuous sequence

Given an unsorted integer array nums, find the length of the longest sequence of consecutive numbers (the sequence elements are not required to be consecutive in the original array). 
* 
* Please design and implement an algorithm with a time complexity of O(n) to solve this problem. 
* 
* 
* 
* Example 1: 
* 
* Input: nums = [100,4,200,1,3,2] 
* Output: 4 
Explanation: The longest continuous sequence of numbers is [1, 2, 3, 4]. Its length is 4.

We consider enumerating each number xxx in the array, considering it as a starting point, and constantly trying to match x+1,x+2,⋯x+1, x+2, \cdotsx+1,x+2,⋯ whether it exists , assuming the longest match is x+yx+yx+y, then the longest continuous sequence starting from xxx is x,x+1,x+2,⋯ ,x+yx, x+1, x+2, \cdots, x+yx,x+1,x+2,⋯,x+y, its length is y+1y+1y+1, we can continue to enumerate and update the answer.

For the matching process, the brute force method is O(n)O(n)O(n) traversing the array to see if the number exists, but in fact a more efficient method is to use a hash table to store the number in the array, check like this Whether a number exists or not can be optimized to a time complexity of O(1)O(1)O(1).

Just because of this, the time complexity of our algorithm will still reach O(n2)O(n^2)O(n 2 
) in the worst case
 (that is, the outer layer needs to enumerate O(n)O(n)O(n) number, the inner layer requires violent matching O(n)O(n)O(n) times), which cannot meet the requirements of the question. But analyzing this process carefully, we will find that a lot of unnecessary enumerations are performed. If it is known that there is a x,x+1,x+2,⋯ ,x+yx, x+1, x+2, \cdots , the continuous sequence of x+yx,x+1,x+2,⋯,x+y, but we start from x+1x+1x+1, x+2x+2x+2 or x+yx+yx+ If you start trying to match at y, the result you get will definitely not be better than the answer starting from the enumeration xxx, so we can just skip it when encountering this situation in the outer loop.

So how to judge whether to skip? Since the number xxx we want to enumerate must have no predecessor number x−1x-1x−1 in the array, otherwise according to the above analysis we will try to match from x−1x-1x−1, so every time we Checking whether x−1x-1x−1 exists in the hash table can determine whether it needs to be skipped.

Implemented through hash table

public class Top3 {

    public static void main(String[] args) {
        int[] num = {100,4,200,1,3,2};
        int longgest = getLongestNum(num);
        System.out.println(longgest);
    }

    /**
     * 由于我们要枚举的数 xxx 一定是在数组中不存在前驱数 x−1 的,不然按照上面的分析我们会从 x−1x-1x−1 开始尝试匹配,因此我们每次在哈希表中检查是否存在 x−1x-1x−1 即能判断是否需要跳过了。
     *
     * @param intData
     * @return
     */
    private static int getLongestNum(int[] intData) {
        Set<Integer> intSet = new HashSet();
        for(int i:intData){
            intSet.add(i);
        }

        int longgest = 0;

        for(int j:intSet)
        {
            if(!intSet.contains(j-1)){
                int curentData = j;
                int longgetIndex = 1;

                while (intSet.contains(curentData+1)){
                    longgetIndex++;
                    curentData++;
                }

                longgest = Math.max(longgest,longgetIndex);
            }
        }

        return longgest;
    }
}

top4 moves zero (dual pointer implementation)

/** 
 * Given an array nums, write a function that moves all 0s to the end of the array while maintaining the relative order of the non-zero elements. 
 * 
 * Note that arrays must be operated on in-place without copying the array. 
 */
public class Top4 {

    private static void moveData(int[] num){
        /*我们创建两个指针 i 和 j,第一次遍历的时候指针 j 用来记录当前有多少 非0 元素。即遍历的时候每遇到一个 非0 元素就将其往数组左边挪,第一次遍历完后,j 指针的下标就指向了最后一个 非0 元素下标。
第二次遍历的时候,起始位置就从 j 开始到结束,将剩下的这段区域内的元素全部置为 0。
        */
        if(num.length==0)
        {
            return;
        }

        int j = 0;

        for(int i=0;i<num.length;i++){
            if(num[i]!=0){
                num[j]=num[i];
                j++;
            }
        }

        for(int i =j;i<num.length;i++){
            num[i] = 0;
        }
    }

    public static void main(String[] args) {
        int[] num = {1,0,2,3,4,0,5,9,0,7,8,0};
        moveData(num);
        for(int i = 0;i<num.length;i++){
            System.out.println(num[i]);
        }
        System.out.println("---------");
        int[] num2 = {5,0,2,3,4,0,5,9,0,7,8,0};
        moveDataTwo(num2);
        for(int i = 0;i<num2.length;i++){
            System.out.println(num2[i]);
        }
    }


    private static void moveDataTwo(int[] num){
        /*这里参考了快速排序的思想,快速排序首先要确定一个待分割的元素做中间点 x,然后把所有小于等于 x 的元素放到 x 的左边,大于 x 的元素放到其右边。
        这里我们可以用 0 当做这个中间点,把不等于 0(注意题目没说不能有负数)的放到中间点的左边,等于 0 的放到其右边。
        这的中间点就是 0 本身,所以实现起来比快速排序简单很多,我们使用两个指针 i 和 j,只要 nums[i]!=0,我们就交换 nums[i] 和 nums[j]
        */

        if(num.length==0){
            return;
        }
        int j=0;
        for(int i=0;i<num.length;i++){
            if(num[i]!=0){
                int temp = num[i];
                num[i] = num[j];
                num[j++] = temp;
            }
        }
    }

}

Guess you like

Origin blog.csdn.net/harryptter/article/details/132875097