01 如何把一个数组循环右移k位
例如:数组{1,2,3,4,5,6,7,8,9}右移两位
第一步 逆序数组子序列 1234567,数组变为765432189
第二步 逆序列数组子序列89,数组变为765432198
第三步 全部逆序,数组变为891234567
/**
* 交换数组
* @param arr
* @param b 开始的下标
* @param e 结束的下标
*/
public static void reverse(int arr[],int b,int e){
for (;b<e;b++,e--){
int tmp = arr[b];
arr[b]=arr[e];
arr[e]=tmp;
}
}
//右移k位
public static void shift_k(int arr[],int k){
int n=arr.length;
k=k%n;//为了防止k比n大,右移k位和k%n位结果一样
reverse(arr,0,n-k-1);
reverse(arr,n-k,n-1);
reverse(arr,0,n-1);
}
public static void main(String[] args) {
int []arr={1,2,3,4,5,6,7,8,9};
shift_k(arr,2);
for (int i:arr){
System.out.print(i+" ");
}
}
02 如何找出数组中第k个最小的数
剪枝法
选一个数tmp = a[n-1] 作为枢纽,把比它小的数都放在它的左边,比它大的数都放在它的右边,然后判断tmp的位置,如果它的位置为k-1,那么它就是死第k个最小的数;如果它的位置小于k-1,那么说明第k个小的元素一定在数组的右半部分,采用递归的方法在数组的右半部分继续查找;否则第k个小的元素在数组的左半部分,采用递归的方法在左半部分继续查找
public static int quitSort(int array[],int low,int high,int k){
int i,j;
int tmp;
if (low>high)
return Integer.MAX_VALUE;
i=low;
j=high;
tmp=array[i];
while (i<j){
while (i<j&&array[j]>tmp)
j--;
if (i<j)
array[i++]=array[j];
while (i<j&&array[i]<tmp)
i++;
if (i<j)
array[j--]=array[i];
}
array[i]=tmp;
if (i+1==k)
return tmp;
else if (i+1>k)
return quitSort(array,low,i-1,k);
else
return quitSort(array,i+1,high,k);
}
public static void main(String[] args) {
int a[] ={10,5,1,9,2,0,18,4};
int k=2;
int i = quitSort(a, 0, a.length - 1, k);
System.out.println("第 "+k+" 小的值为: "+i);
}
03 如何找出数组中只出现一次的数字
问题描述:一个整形数组里除了一个数字之外,其他数字都出现了两次。找出这个只出现1次的数字。要求时间复杂度为O(n),空间复杂度为O(1)
异或法:任何数字异或它自己都等于0
public static int findNotDouble(int[] arr){
int n=arr.length;
int result=arr[0];
for (int i=1;i<n;i++){
result ^=arr[i];
}
return result;
}
public static void main(String[] args) {
int arr[]={1,2,1,2,3,4,5,4,5};
System.out.println( findNotDouble(arr));
}
引申:如果题目改成数组A中,一个整形数组里除了一个数字之外,其他数字都出现3次,嘛呢如何找出这个数?
public static int findOnce(int a[],int appearTimes){
int n=a.length;
int[] bitCount = new int[32];
//计算数组中所有数组对应的二进制数各个位置上出现1次的数
for (int i=0;i<n;i++){
for (int j=0;j<32;j++){
bitCount[j]+=((a[i]>>j)&1);
}
}
//若某位上的结果不能被整除,则可定目标数字在这一位上
int appearOne =0;
for (int i=0;i<32;i++){
if (bitCount[i]%appearTimes!=0)
appearOne+=(1<<i);
}
return appearOne;
}
public static void main(String[] args) {
int arr1[]={1,1,1,2,2,2,3,4,4,4};
System.out.println( findOnce(arr1,1));
}
04 如何找出数组中唯一的重复元素
问题描述:数组a[N] ,1~N-1这N-1个数存放在a[N]中,其中某个数重复1次。写一个函数,找出被重复的数字。要求没个数组元素只能访问1次,并且不用辅助空间。
蛮力法:
采用数组求和,因为只用一个数字重复1次,而又是连续的,根据累加和原理,对数组的所有项求和,然后减去1~N-1的和,及所求的重复数。
public static int xor_FindDup(int []a){
int n=a.length;
int tmp1=0;
int tmp2=0;
for (int i=0;i<n-1;i++){
tmp1+=(i+1);
tmp2+=a[i];
}
tmp2+=a[n-1];
int result =tmp2-tmp1;
return result;
}
public static void main(String[] args) {
int a[]={1,2,3,3,4,5};
System.out.println(xor_FindDup(a));
}
异或法:
每两个相异的执行异或运算之后,结果为1,每两个相同的数执行异或运算之后,结果为0,所以数组a[N]中的N个数异或结果与1~N-1异或的结果在做异或运算,得到的值即为所求。
public static int xor_FindDup1(int arr[]){
int n=arr.length;
int result=0;
for (int i=0;i<n;i++)
result ^=arr[i];
for (int i=1;i<n;i++)
result ^=i;
return result;
}
public static void main(String[] args) {
int a[]={1,2,3,3,4,5};
System.out.println(xor_FindDup1(a));
}
空间换时间法:
public static int findInteger(int[] a){
int n=a.length;
boolean[] arrayFlag=new boolean[n];
int result=0;
for (int i=0;i<n;i++){
arrayFlag[i]=false;
}
for (int i=0;i<n;i++){
if (arrayFlag[a[i]]==false)
arrayFlag[a[i]]=true;
else
result =a[i];
}
return result;
}
public static void main(String[] args) {
int a[]={1,2,3,3,4,5};
System.out.println(findInteger(a));
}
引申:取值为[1,n-1]含n个元素的整数数组,至少存在一个重复数,及可能存在多个重复数,O(n)时间内找出其中任意一个重复数,例如:array[]={1,2,2,4,5,4},2和4均是重复元素
取反法:
如果遍历到数组中元素为i,那么把a[i]的值取反,如果i在数组出现了1次,那么a[i]会经过两次取反操作,a[i]的值跟原始的值相等,且为正数;如果i出现了1次,那么a[i]的值为原始值得相反数,且为负数,可以根据这个原理实现
public static int findInteger1(int[] a){
int n=a.length;
int result=Integer.MAX_VALUE;
for (int i=0;i<n;i++){
if (a[i]>0){
a[a[i]]=-a[a[i]];
}else{
a[-a[i]]=-a[-a[i]];
}
}
for(int i=1;i<n;i++){
if (a[i]>0)
result=i;
else
a[i]=-a[i];
}
return result;
}
public static void main(String[] args) {
int a[]={1,2,3,3,4,5};
System.out.println(findInteger1(a));
}
判断单链表是否有环法:
本题转化为,已知一个单链表中存在环,找出换的入口点。
public static int findInteger2(int a[]){
int x,y;
x=y=0;
do {
x=a[a[x]];
y=a[y];
}while (x!=y);
x=0;
do {
x=a[x];
y=a[y];
}while (x!=y);
return x;
}
public static void main(String[] args) {
int a[]={1,2,3,3,4,5};
System.out.println(findInteger2(a));
}
05 如何用递归方法求一个整数数组的最大元素
先定义一个变量max为数组的第一个元素,然后从第二个元素开始遍历,咋及便利的过程中,每个元素都与max的值比较,若个元素的值比max的值大,则吧该元素的值赋给max。
private static int max(int a,int b){
return a>b?a:b;
}
public static int maxNum(int a[],int begin){
int length=a.length-begin;
if(length==1){
return a[begin];
}else {
return max(a[begin],maxNum(a,begin+1));
}
}
public static void main(String[] args) {
int a[]={11,1,24,8,9,12,6,7,20};
System.out.println(maxNum(a,0));
}