給定一個長度不小於2的數組arr。java
寫一個函數調整arr,使arr中要麼所有的偶數位上都是偶數,要麼所有的奇數位上都是奇數上。 要求:假設數組長度爲N。時間複雜度請達到O(N),額外空間複雜度請達到O(1),下標0,2,4,6...算做偶數位,下標1,3,5,7...算做奇數位,好比[1,2,3,4]調整爲[2,1,4,3]就能夠
數組
分析:函數
時間複雜度請達到O(N),就不能用多重循環。額外空間複雜度請達到O(1),,也就不能用輔助的數組之類的,就是要在單次掃描中,經過交換2個數的位置來實現。post
事實上咱們換個思惟來想,假設有2個一樣長度數組A,B。知足要麼A數組全是偶數。要麼B數組全是奇數,是否是就能很是快的有思路了。想一下再看如下分析。spa
2個指針P_A和P_B分別指向A,B,首先P_A找出第一個奇數,而後P_B找出第一個偶數,交換。而後循環這個方案,直到某個指針達到數組的末尾。指針
事實上這個題和上面的思路同樣。至關於把2個數組交叉放在一塊兒。偶數位置的至關於A數組。奇數位置至關於B數組。僅僅是每次移動2個位置code
代碼:orm
public class Solution { /** * 奇數位上都是奇數或者偶數位上都是偶數 * 輸入:數組arr。長度大於2 * 將arr調整成奇數位上都是奇數或者偶數位上都是偶數 */ public void oddInOddEvenInEven(int[] arr) { int len = arr.length; if (len <= 2) { return; } int even = 0; int odd = 1; while (even < len && odd < len) { if (arr[even] % 2 != 0) { odd = findEven(arr, odd); if (odd < len) { int temp = arr[odd]; arr[odd] = arr[even]; arr[even] = temp; } } even += 2; } } private int findEven(int[] arr, int odd) { for (int i = odd; i < arr.length; i+=2) { if (arr[i] % 2 == 0) { return i; } } return arr.length; } }
import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class Solution { /** * 正數數組中的最小不可組成和 * 輸入:正數數組arr * 返回:正數數組中的最小不可組成和 */ public int getFirstUnFormedNum(int[] arr) { int len=arr.length; if(len==0){ return 0; } if(len==1){ return arr[0]+1; } Arrays.sort(arr); if(len==2){ return arr[1]-arr[0]==1?arr[1]+1:arr[0]+1; } int min=arr[0]; int max=arr[len-1]; int sum=0; for(int i=0;i<arr.length;i++){ sum+=arr[i]; } int[] flag=new int[sum-min+1]; Set<Integer> integers=new HashSet<Integer>(); integers.add(arr[0]); integers.add(arr[1]); integers.add(arr[1]+arr[0]); int set_max=arr[1]+arr[0]; setFlag(arr[0],min,flag); setFlag(arr[1],min,flag); setFlag(set_max,min,flag); for(int i=2;i<len;i++){ int temp=arr[i]; Set<Integer> temp_set=new HashSet<Integer>(integers); temp_set.add(temp); setFlag(temp,min,flag); for (Iterator iterator = integers.iterator(); iterator.hasNext();) { int v = (Integer) iterator.next(); temp_set.add(v+temp); setFlag(v+temp,min,flag); } set_max+=temp; integers=temp_set; int res=judge(flag,temp-min); if(res!=-1){ return res+min; } } int res=judge(flag,sum-min); if(res!=-1){ return res+min; } return sum+1; } private int judge(int[] flag, int max) { for(int i=0;i<max;i++){ if(flag[i]==0){ return i; } } return -1; } private void setFlag(int i, int min, int[] flag) { flag[i-min]=1; } }排序
遊戲勝負的規定: 假設玩家1最後得到的分數大於玩家2,則玩家1獲勝; 假設玩家2最後得到的分數大於玩家1,則玩家2獲勝; 因爲玩家1先拿硬幣。因此假設最後兩人得到分數同樣則玩家2獲勝; 給定一個數組arr。表示硬幣的面值和排列情況,請返回終於獲勝者的分數。遊戲
樣例: arr=[8,7,5,3] 玩家1將獲勝,分數爲13 因此返回13 arr=[1,9,1] 玩家2將獲勝,分數爲9 因此返回9
public class Solution { /** * 獲得硬幣博弈問題的獲勝分值 * 輸入:表明硬幣排列狀況的數組arr * 返回:硬幣博弈問題的獲勝分值 */ public int getWinValue(int[] arr) { int len=arr.length; int[][] d=new int[len][len]; int sum=0; for(int i=0;i<len;i++){ d[i][i]=arr[i]; sum+=arr[i]; } for(int w=1;w<len;w++){ for(int i=0;i<len-w;i++) { rule(arr,i,i+w,d); } } return (Math.abs(d[0][len-1])+sum)/2; } private void rule(int[] arr, int i, int w, int[][] d) { int left=arr[i]-d[i+1][w]; int right=arr[w]-d[i][w-1]; if(left>right){ d[i][w]=left; }else{ d[i][w]=right; } } }