數組方法:
1、length:
arr.length返回數組長度
2、Arrays.asList()
將數組轉化成List集合的方法。
3、Arrays.fill()函數
填充a1數組中的每個元素都是value。
Arrays.fill( a1, value );
注:a1是一個數組變量,value是一個a1中元素數據類型的值。
1、長度最小的子數組
暴力破解法:
class Solution { public int minSubArrayLen(int target, int[] nums) { int min = Integer.MAX_VALUE; for(int i =0;i<nums.length;i++){ int sum = nums[i]; if(sum >= target){ return 1; } for(int j = i+1; j<nums.length;j++){ sum += nums[j]; if(sum >= target){ min = Math.min(min,j-i+1); } } } return min == Integer.MAX_VALUE ? 0 : min; } }
2、尋找兩個正序數組的中位數
給定兩個大小分別為 m
和 n
的正序(從小到大)數組 nums1
和 nums2
。請你找出並返回這兩個正序數組的 中位數 。
示例 1:
輸入:nums1 = [1,3], nums2 = [2]
輸出:2.00000
解釋:合並數組 = [1,2,3] ,中位數 2
示例 2:
輸入:nums1 = [1,2], nums2 = [3,4]
輸出:2.50000
解釋:合並數組 = [1,2,3,4] ,中位數 (2 + 3) / 2 = 2.5
示例 3:
輸入:nums1 = [0,0], nums2 = [0,0]
輸出:0.00000
示例 4:
輸入:nums1 = [], nums2 = [1]
輸出:1.00000
示例 5:
輸入:nums1 = [2], nums2 = []
輸出:2.00000
class Solution { public double findMedianSortedArrays(int[] nums1, int[] nums2) { int[] nums; int m = nums1.length; int n = nums2.length; nums = new int[m+n]; if(m == 0){ if(n % 2 == 0){ return (nums2[n/2 - 1] + nums2[n/2]) / 2.0; }else{ return nums2[n/2]; } } if(n == 0){ if(m % 2 == 0){ return (nums1[m/2 - 1] + nums1[m/2]) / 2.0; }else{ return nums1[m/2]; } } int count = 0; int i = 0; int j = 0; while(count != (m + n)){ if(i == m){ while(j != n){ nums[count++] = nums2[j++]; } break; } if(j == n){ while(i != m){ nums[count++] = nums1[i++]; } break; } if(nums1[i] < nums2[j]){ nums[count] = nums1[i]; count++; i++; }else{ nums[count] = nums2[j]; count++; j++; } } if((m+n) % 2 == 0){ return (nums[(m+n)/2 - 1] + nums[(m+n) / 2]) / 2.0; }else{ return nums[(m+n) / 2] ; } } }
解析:
暴力破解法:先將兩個數組合並,兩個有序數組的合並也是歸並排序中的一部分。然后根據奇數,還是偶數,返回中位數。
3、數組中重復的數據
給定一個整數數組 a,其中1 ≤ a[i] ≤ n (n為數組長度), 其中有些元素出現兩次而其他元素出現一次。
找到所有出現兩次的元素。
示例:
輸入: [4,3,2,7,8,2,3,1] 輸出: [2,3]
class Solution { public List<Integer> findDuplicates(int[] nums) { List<Integer> res = new ArrayList<>(); if(nums == null || nums.length == 0){ return res; } Set<Integer> set = new HashSet<>(); for(int n : nums){ if(!set.add(n)){ res.add(n); } } return res; } }
4、找到所有數組中消失的數字
給你一個含 n 個整數的數組 nums ,其中 nums[i] 在區間 [1, n] 內。請你找出所有在 [1, n] 范圍內但沒有出現在 nums 中的數字,並以數組的形式返回結果。
示例 1:
輸入:nums = [4,3,2,7,8,2,3,1] 輸出:[5,6]
示例 2:
輸入:nums = [1,1] 輸出:[2]
class Solution { public List<Integer> findDisappearedNumbers(int[] nums) { List<Integer> res = new ArrayList<>(); if(nums == null || nums.length == 0){ return res; } int[] tmp = new int[nums.length]; for(int n : nums){ if(n >= 1 && n <= nums.length){ tmp[n - 1] = 1; } } for(int i=0;i<nums.length;i++){ if(tmp[i] == 0){ res.add(i+1); } } return res; } }
5、二分查找
給定一個 n 個元素有序的(升序)整型數組 nums 和一個目標值 target ,寫一個函數搜索 nums 中的 target,如果目標值存在返回下標,否則返回 -1。
輸入:nums
= [-1,0,3,5,9,12],target
= 9 輸出: 4 解釋: 9 出現在nums
中並且下標為 4
輸入:nums
= [-1,0,3,5,9,12],target
= 2 輸出: -1 解釋: 2 不存在nums
中因此返回 -1
class Solution { public int search(int[] nums, int target) { if(nums[0] > target || nums[nums.length - 1] < target){ return -1; } int left = 0; int right = nums.length; while(left < right){ int middle = (left + right) / 2; if(nums[middle] > target){ right = middle; }else if(nums[middle] < target){ left = middle + 1; }else{ return middle; } } return -1; } }
解析:
這道題目的前提是數組為有序數組,同時題目還強調數組中無重復元素,因為一旦有重復元素,使用二分查找法返回的元素下標可能不是唯一的,這些都是使用二分法的前提條件,當大家看到題目描述滿足如上條件的時候,可要想一想是不是可以用二分法了。
二分查找涉及的很多的邊界條件,邏輯比較簡單,但就是寫不好。例如到底是 while(left < right)
還是 while(left <= right)
,到底是right = middle
呢,還是要right = middle - 1
呢?
大家寫二分法經常寫亂,主要是因為對區間的定義沒有想清楚,區間的定義就是不變量。要在二分查找的過程中,保持不變量,就是在while尋找中每一次邊界的處理都要堅持根據區間的定義來操作,這就是循環不變量規則。
寫二分法,區間的定義一般為兩種,左閉右閉即[left, right],或者左閉右開即[left, right)。
下面我用這兩種區間的定義分別講解兩種不同的二分寫法。
二分法第一種寫法
第一種寫法,我們定義 target 是在一個在左閉右閉的區間里,也就是[left, right] (這個很重要非常重要)。
區間的定義這就決定了二分法的代碼應該如何寫,因為定義target在[left, right]區間,所以有如下兩點:
- while (left <= right) 要使用 <= ,因為left == right是有意義的,所以使用 <=
- if (nums[middle] > target) right 要賦值為 middle - 1,因為當前這個nums[middle]一定不是target,那么接下來要查找的左區間結束下標位置就是 middle - 1
例如在數組:1,2,3,4,7,9,10中查找元素2,如圖所示:
二分法第二種寫法
如果說定義 target 是在一個在左閉右開的區間里,也就是[left, right) ,那么二分法的邊界處理方式則截然不同。
有如下兩點:
- while (left < right),這里使用 < ,因為left == right在區間[left, right)是沒有意義的
- if (nums[middle] > target) right 更新為 middle,因為當前nums[middle]不等於target,去左區間繼續尋找,而尋找區間是左閉右開區間,所以right更新為middle,即:下一個查詢區間不會去比較nums[middle]
在數組:1,2,3,4,7,9,10中查找元素2,如圖所示:(注意和方法一的區別)