Given an circular integer array (the next element of the last element is the first element), find a continuous subarray in it, where the sum of numbers is the biggest. Your code should return the index of the first number and the index of the last number.數組
If duplicate answers exist, return any of them.ide
Give [3, 1, -100, -3, 4]
, return [4,1]
.spa
先是一個超時了的代碼。。雖然剪了枝但仍是會超時。3d
1 public class Solution { 2 /** 3 * @param A an integer array 4 * @return A list of integers includes the index of the first number and the index of the last number 5 */ 6 public ArrayList<Integer> continuousSubarraySumII(int[] A) { 7 int l = A.length; 8 int s = 0; 9 int e = 0; 10 int ms = 0; 11 int me = 0; 12 int sum = A[0]; 13 int max = A[0]; 14 ArrayList<Integer> list = new ArrayList(); 15 16 if(l == 1){ 17 list.add(0); 18 list.add(0); 19 return list; 20 } 21 22 23 for(int j = 0;j<l;j++) { 24 if(A[j] <= 0) continue; 25 sum = A[j]; 26 s = j; 27 e = j; 28 for(int i = (j+1)%l;j!=i;i = (i+1)%l){ 29 if(A[i] < 0) { 30 if(sum > max) { 31 max = sum; 32 ms = s; 33 me = e; 34 } 35 } 36 37 if(sum < 0) { 38 sum = A[i]; 39 s = i; 40 e = i; 41 }else { 42 sum += A[i]; 43 e = i; 44 } 45 } 46 } 47 48 49 if(max > sum) { 50 list.add(ms); 51 list.add(me); 52 }else { 53 list.add(s); 54 list.add(e); 55 } 56 return list; 57 } 58 }
而後很仔細的想了一下。設0<=a<=b<=A.length,最大和區間只有兩種狀況:[a,b]和[b,A.length-1]U[0,a];只要找出這兩種狀況下的最大區間和,比較一下大的那個就是所求區間。code
第一種狀況就是求不頭尾相連數組A的最大和區間。第二種是求不頭尾相連A的最小子區間[a+1,b-1](或者說是-A的最大區間和)。blog
敲出一段亂糟糟的代碼終於AC了,容我去擼一把。ci
1 public class Solution { 2 /** 3 * @param A an integer array 4 * @return A list of integers includes the index of the first number and the index of the last number 5 */ 6 public ArrayList<Integer> continuousSubarraySumII(int[] A) { 7 int[] nums = A; 8 int sum = nums[0]; 9 int allsum = nums[0]; 10 int max = nums[0]; 11 int min = nums[0]; 12 int msum = nums[0]; 13 int mins = 0; 14 int mine = 0; 15 int s1 = 0; 16 int e1 = 0; 17 int s = 0; 18 int e = 0; 19 int ms = 0; 20 int me = 0; 21 ArrayList<Integer> list = new ArrayList<Integer>(); 22 23 for(int i = 1 ;i < nums.length ;i++) { 24 allsum += nums[i]; 25 if(nums[i] < 0) { 26 if(sum > max) { 27 max = sum; 28 ms = s; 29 me = e; 30 } 31 } 32 33 if(nums[i] > 0) { 34 if(msum < min) { 35 min = msum; 36 mins = s1; 37 mine = e1; 38 } 39 } 40 41 if(sum < 0) { 42 sum = nums[i]; 43 s = i; 44 e = i; 45 }else { 46 sum+=nums[i]; 47 e++; 48 } 49 50 if(msum > 0) { 51 msum = nums[i]; 52 s1 = i; 53 e1 = i; 54 }else { 55 msum+=nums[i]; 56 e1++; 57 } 58 } 59 60 if(sum > max) { 61 max = sum; 62 ms = s; 63 me = e; 64 } 65 if(msum < min) { 66 min = msum; 67 mins = s1; 68 mine = e1; 69 } 70 int val = allsum - min; 71 if(val > max && (mins != 0 && mine != A.length-1)) { 72 ms = mine + 1; 73 me = mins - 1; 74 } 75 76 list.add(ms); 77 list.add(me); 78 return list; 79 } 80 }
還有一個想法是將A拷貝一份接上,而後至關於求這整個數組的最大和區間。想法是設置一個int flag容許遍歷數組尾部兩次;同時限制區間長度不能超過A.length。可是WA了。快折騰一下午了實在不想搞了先放着之後想起來再說把。element
1 public class Solution { 2 /** 3 * @param A an integer array 4 * @return A list of integers includes the index of the first number and the index of the last number 5 */ 6 public ArrayList<Integer> continuousSubarraySumII(int[] A) { 7 int l = A.length; 8 int s = 0; 9 int e = 0; 10 int ms = 0; 11 int me = 0; 12 int sum = A[0]; 13 int max = A[0]; 14 int flag = 2;//容許遍歷數組尾部2次 15 ArrayList<Integer> list = new ArrayList(); 16 17 if(l == 1){ 18 list.add(0); 19 list.add(0); 20 return list; 21 } 22 23 int i = 1; 24 while(flag > 0) { 25 if(i == l - 1) flag--; 26 if(A[i] < 0) { 27 if(sum > max) { 28 max = sum; 29 ms = s; 30 me = e; 31 } 32 } 33 34 if(sum < 0) { 35 sum = A[i]; 36 s = i; 37 e = 0; 38 }else { 39 if(e + 1 > l - 1) break; 40 sum += A[i]; 41 e++; 42 } 43 44 i = (i + 1) % l; 45 } 46 47 48 if(max > sum) { 49 list.add(ms); 50 list.add((me+ms)%l); 51 }else { 52 list.add(s); 53 list.add((e+s)%l); 54 } 55 return list; 56 } 57 }