LeetCode:Array

1.Array

1.Contains Duplicate

Given an array of integers, find if the array contains any duplicates. Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.

运用merge sort的实现:

public class Solution {

    //success 1
    //运用merge sort的思想,如果在sort或merge中有相同的情况,那么返回true,否则为false。时间复杂度为O(NlogN)
    public boolean containsDuplicate(int[] nums) {
        return sort(nums,0,nums.length-1);
    }

    /* Java program for Merge Sort */
        // Merges two subarrays of arr[].
        // First subarray is arr[l..m]
        // Second subarray is arr[m+1..r]
        boolean merge(int arr[], int l, int m, int r)
        {
            // Find sizes of two subarrays to be merged
            int n1 = m - l + 1;
            int n2 = r - m;

        /* Create temp arrays */
            int L[] = new int [n1];
            int R[] = new int [n2];

        /*Copy data to temp arrays*/
            for (int i=0; i<n1; ++i)
                L[i] = arr[l + i];
            for (int j=0; j<n2; ++j)
                R[j] = arr[m + 1+ j];


        /* Merge the temp arrays */

            // Initial indexes of first and second subarrays
            int i = 0, j = 0;

            // Initial index of merged subarry array
            int k = l;
            while (i < n1 && j < n2)
            {
                if (L[i] < R[j])
                {
                    arr[k] = L[i];
                    i++;
                }
                else if(L[i] > R[j])
                {
                    arr[k] = R[j];
                    j++;
                }else{
                    return true;
                }
                k++;
            }

        /* Copy remaining elements of L[] if any */
            while (i < n1)
            {
                arr[k] = L[i];
                i++;
                k++;
            }

        /* Copy remaining elements of L[] if any */
            while (j < n2)
            {
                arr[k] = R[j];
                j++;
                k++;
            }
            return false;
        }

        // Main function that sorts arr[l..r] using
        // merge()
        boolean sort(int arr[], int l, int r)
        {
            if (l < r)
            {
                // Find the middle point
                //注意:此种写法容易引起溢出
                //int m = (l+r)/2;
                //正确写法
                int m = l+(r-l)/2;
                // Sort first and second halves
                boolean left = sort(arr, l, m);
                boolean right = sort(arr , m+1, r);

                // Merge the sorted halves
                boolean merge =  merge(arr, l, m, r);
                if(left||right||merge){
                    return true;
                }
            }
            return false;
        }
}

此外,还有其他的一些方法,如果追求小的时间复杂度,可以用hashTable来实现。参考:

其他解法

2.Median of Two Sorted Arrays

寻找两个数组连接起来的中位数。

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

Example 1:
nums1 = [1, 3]
nums2 = [2]

The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]

The median is (2 + 3)/2 = 2.5

我并没有想出实现的方式,参考Discuss中大神的思路。自己动手实现一下:

public class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
    int m = nums1.length;
    int n = nums2.length;

    if (m > n) {
        return findMedianSortedArrays(nums2, nums1);
    }

    int i = 0, j = 0, imin = 0, imax = m, half = (m + n + 1) / 2;
    double maxLeft = 0, minRight = 0;
    while(imin <= imax){
        i = (imin + imax) / 2;
        j = half - i;
        if(j > 0 && i < m && nums2[j - 1] > nums1[i]){
            imin = i + 1;
        }else if(i > 0 && j < n && nums1[i - 1] > nums2[j]){
            imax = i - 1;
        }else{
            if(i == 0){
                maxLeft = (double)nums2[j - 1];
            }else if(j == 0){
                maxLeft = (double)nums1[i - 1];
            }else{
                maxLeft = (double)Math.max(nums1[i - 1], nums2[j - 1]);
            }
            break;
        }
    }
    if((m + n) % 2 == 1){
        return maxLeft;
    }
    if(i == m){
        minRight = (double)nums2[j];
    }else if(j == n){
        minRight = (double)nums1[i];
    }else{
        minRight = (double)Math.min(nums1[i], nums2[j]);
    }

    return (double)(maxLeft + minRight) / 2;
}
}

3.Find Peak Element

A peak element is an element that is greater than its neighbors.

Given an input array where num[i] ≠ num[i+1], find a peak element and return its index.

The array may contain multiple peaks, in that case return the index to any one of the peaks is fine.

You may imagine that num[-1] = num[n] = -∞.

For example, in array [1, 2, 3, 1], 3 is a peak element and your function should return the index number 2.

代码如下:

public class Solution {

    //success 1
    // public int findPeakElement(int[] nums) {
    //     if(nums.length==1){
    //         return 0;
    //     }
    //     for (int i = 0; i < nums.length; i++) {
    //         if (i == 0) {
    //             if (nums[i] > nums[i + 1]) {
    //                 return 0;
    //             }
    //         } else if (i == nums.length - 1) {
    //             if (nums[i] > nums[i - 1]) {
    //                 return nums.length - 1;
    //             }
    //         } else {
    //             if (nums[i] > nums[i - 1] && nums[i] > nums[i + 1]) {
    //                 return i;
    //             }
    //         }

    //     }
    //     return 0;
    // }

    //success 2
    //简化1
    public int findPeakElement(int[] nums) {
        for (int i = 1; i < nums.length; i++) {
            if(nums[i-1]>nums[i]){
                return i-1;
            }
        }
        return nums.length-1;
    }
}

除了上面两种简单的方法,还有O(logN)的方法:

This problem is similar to Local Minimum. And according to the given condition, num[i] != num[i+1], there must exist a O(logN) solution. So we use binary search for this problem.

1.If num[i-1] < num[i] > num[i+1], then num[i] is peak
2.If num[i-1] < num[i] < num[i+1], then num[i+1…n-1] must contains a peak
3.If num[i-1] > num[i] > num[i+1], then num[0…i-1] must contains a peak
4.If num[i-1] > num[i] < num[i+1], then both sides have peak

方法三代码:

public class Solution {
    //success 3
    //运用binary search
    public int findPeakElement(int[] nums) {
        return findPeak(nums,0,nums.length-1);
    }

    public int findPeak(int[] num,int start,int end){
        if(start == end){
        return start;
    }else if(start+1 == end){
        if(num[start] > num[end]) return start;
        return end;
    }else{
        //注意:此种写法容易引起溢出
        //int m = (start+end)/2;
        //正确写法
        int m = start+(end-start)/2;
        //condition 1
        if(num[m] > num[m-1] && num[m] > num[m+1]){

            return m;
        //condition 3
        }else if(num[m-1] > num[m] && num[m] > num[m+1]){

            return findPeak(num,start,m-1);
        //condition 2 and conditon 4
        }else{

            return findPeak(num,m+1,end);

        }
    }

}
}

4.Find Minimum in Rotated Sorted Array

Suppose a sorted array is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

Find the minimum element.

You may assume no duplicate exists in the array.

运用binary search,参考

public class Solution {
    public int findMin(int[] nums) {
        if (nums==null || nums.length==0) { return Integer.MIN_VALUE; } 
        int left = 0, right = nums.length-1;
        //保证比较数组中至少有三个元素
        while (left < right-1) {  // while (left < right-1) is a useful technique
            int mid = left + (right-left)/2;
            if (nums[mid] > nums[right]) { left = mid; }
            else { right = mid; }
        }
        if (nums[left] > nums[right]) { return nums[right]; }
        return nums[left];
    }
}

5.Find Minimum in Rotated Sorted Array II

4题上的变种(考虑有重复的元素):

Follow up for “Find Minimum in Rotated Sorted Array”:
What if duplicates are allowed?

Would this affect the run-time complexity? How and why?

public class Solution {
    public int findMin(int[] nums) {
        if (nums==null || nums.length==0) { return Integer.MIN_VALUE; } 
        int left = 0, right = nums.length-1;
        //保证比较数组中至少有三个元素
        while (left < right-1) {  // while (left < right-1) is a useful technique
            int mid = left + (right-left)/2;
            if (nums[mid] > nums[right]) { left = mid; }
            else if(nums[mid] < nums[right]) { right = mid; }
            //相等情况,不能确定在左还是右,只能减少一点边界
            else{
                right-=1;
            }
        }
        if (nums[left] > nums[right]) { return nums[right]; }
        return nums[left];
    }
}

注意:Java曾经的一个系统级的binary search bug,可以google “binary search bug”,这个bug是,当使用int mid = (left + right)/2;时,如果当left和right都很大时,left+right将发生overflow,进而产生负数,Java在2006年已经在系统级别binary search上进行了修复。但是我们自己手写代码时,如果不注意这个bug,在left和right都很大时,就会产生错误。所以我推荐使用int mid = left + (right-left)/2;,当然最精确的方法是看看Java源码中的实现,然后照着改写之。
相关文章参考:
google blog
java bug

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值