标签:
给定一个长度不小于2的数组arr。 写一个函数调整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个数的位置来实现。
其实我们换个思维来想,如果有2个相同长度数组A,B,满足要么A数组全是偶数,要么B数组全是奇数,是不是就能很快的有思路了,想一下再看下面分析。
2个指针P_A和P_B分别指向A,B,首先P_A找出第一个奇数,然后P_B找出第一个偶数,交换,然后循环这样的方法,直到某个指针达到数组的末尾。
其实这个题和上面的思路一样,相当于把2个数组交叉放在一起,偶数位置的相当于A数组,奇数位置相当于B数组,只是每次移动2个位置
代码:
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;
}
}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;
}
}
}标签:
原文地址:http://blog.csdn.net/lizo_is_me/article/details/46461437