1.如何找出数组中重复唯一的重复的元素
题目描述:
数字1~1000放在含有1001个元素的数组中,其中只有唯一的一个元素值重复,其他数字均只出现一次。设计一个算法,将重复元素找出来,要求每个数组元素只能访问一次。如果不使用辅助存储空间,能否设计一个算法实现?
import java.util.Hashtable;
/**
* @author 龙御修
* @create 2022-05-04 10:04
*/
public class FindRepetitionArrays {
//在数组中找出唯一重复的元素
public static int findDup(int[] array){
if(null==array)
return -1;
int len= array.length;
Hashtable<Integer,Integer> hashtable=new Hashtable<>();
int i;
for(i=0;i<len-1;i++)
hashtable.put(i,0);
for(i=0;i<len;i++){
if(hashtable.get(array[i]-1)==0){
hashtable.put(array[i]-1,array[i]-1);
}else {
return array[i];
}
}
return -1;
}
public static void main(String[] args) {
int[] array={1,3,4,2,5,3};
System.out.println(findDup(array));
}
}
hashtable:哈希表(HashTable)又叫做散列表,是根据关键码值(即键值对)而直接访问的数据结构。
2.如何查找数组中元素的最大值和最小值
题目描述:
给定数组a1, a2, a3, …, an,要求找出数组中的最大值和最小值。假设数组中的值两两各不相同。
分治法
/**
* @author 龙御修
* @create 2022-05-04 17:13
*/
public class MaxMinArrays {
private int max;
private int min;
public int getMax() {
return max;
}
public int getMin() {
return min;
}
public void GetmaxAndmin(int[] arr){
if(arr==null){
System.out.println("参数不合法");
return;
}
int i=0;
int len=arr.length;
max=arr[0];
min=arr[0];
//两两分组,把较小的数放到左半部,较大的放到右半部
for(i=0;i<len-1;i+=2){
if(arr[i]>arr[i+1]){
int tmp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=tmp;
}
}
//在各个分组的左半部分找出最小值
min=arr[0];
for(i=2;i<len;i+=2) {
if (arr[i] < min) {
min = arr[i];
}
}
//在各个分组找出右半部分最大值
max=arr[1];
for(i=3;i<len;i+=2) {
if (arr[i] > max) {
max = arr[i];
}
}
//如果数组中元素个数是奇数个,最后一个元素被分为一组,需要特殊处理
if(len%2==1){
if(max<arr[len-1])
max=arr[len-1];
if(min>arr[len-1])
min=arr[len-1];
}
}
public static void main(String[] args) {
int[] array={7,3,19,40,4,7,1};
MaxMinArrays m=new MaxMinArrays();
m.GetmaxAndmin(array);
System.out.println("max="+m.getMax());
System.out.println("min="+m.getMin());
}
}
3.如何找出旋转数组最小元素
题目描述:
把一个有序数组最开始的若干个元素搬到数组的末尾,称之为数组的旋转。输入一个排好序的数组的一个旋转,输出旋转数组的最小元素。例如,数组{3, 4, 5, 1, 2}为数组{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1。
/**
* @author 龙御修
* @create 2022-05-04 17:39
*/
public class RpinAarrays {
public static int getMin(int[] arr,int low,int high){
//如果旋转个数为0,即没有旋转,单独处理,直接返回数组头元素
if(high<low)
return arr[0];
//只剩一个元素一定是最小值
if(high==low)
return arr[low];
//mid=(low+high)/2,采用下面写法防止溢出
int mid=low+((high-low)>>1);
//判断是否arr[mid]为最小值
if(arr[mid]<arr[mid-1])
return arr[mid];
//判断是否arr[mid+1]为最小值
else if(arr[mid+1]<arr[mid])
return arr[mid+1];
//最小值一定在数组左半部
else if(arr[high]>arr[mid])
return getMin(arr,low,mid-1);
// 最小值一定在数组右半部
else if(arr[mid]>arr[low])
return getMin(arr,mid+1,high);
//arr[low]==arr[mid]&&arr[high]==arr[mid]
//这种情况下无法确定最小值所在的位置,需要在左右两部分分别进行查找
else
return Math.min(getMin(arr,low,mid-1),getMin(arr,mid+1,high));
}
public static int getMin(int[] arr){
if(arr==null){
System.out.println("参数不合法");
return -1;
}else
return getMin(arr,0, arr.length-1);
}
public static void main(String[] args) {
int[] array1={5,6,1,2,3,4};
int min=getMin(array1);
System.out.println(min);
int[]array2={1,1,0,1};
min=getMin(array2);
System.out.println(min);
}
}
4. 如何实现旋转数组功能?
package array;
public class RpinArray {
public static void swap(int[] arr,int low,int high){
//交换数组low到high的内容
for(;low<high;low++,high--){
int tmp=arr[low];
arr[low]=arr[high];
arr[high]=tmp;
}
}
public static void rotatearr(int[] arr,int div){
if(arr==null||div<0||div>= arr.length){
System.out.println("参数不合法");
return;
}
//不需要旋转
if(div==0||div== arr.length-1)
return;
//交换第一个子数组的内容
swap(arr,0,div);
//交换第二个数组内容
swap(arr,div+1, arr.length-1);
//交换整个数组的元素
swap(arr,0, arr.length-1);
}
public static void main(String[] args) {
int[] arr={1,2,3,4,5};
rotatearr(arr,2);
for (int i=0;i< arr.length;i++)
System.out.print(arr[i]+" ");
}
}
5.如果找出数组中丢失的数
题目描述:
给定一个由n-1个整数组成的未排序的数组序列,其元素都是1到n中的不同的整数。请写出一个寻找数组序列中缺失整数的线性时间算法。
package array;
public class DropArray {
//累加法
public static int getnum(int[] arr){
if(arr==null||arr.length<=0){
System.out.println("参数不合法");
return -1;
}
int suma=0,sumb=0;
int i;
for(i=0;i<arr.length;i++){
suma=suma+arr[i];
sumb=sumb+i;
}
sumb=sumb+arr.length+arr.length+1;
return sumb-suma;
}
//异减法
public static int getnum1(int[]arr){
if(arr==null||arr.length<=0){
System.out.println("参数不合法");
return -1;
}
int a=arr[0],b=1;
int i;
int len=arr.length;
for(i=1;i<len;i++){
a=a^arr[i];
}
for(i=2;i<=len+1;i++){
b=b^i;
}
return a^b;
}
public static void main(String[] args) {
int[] arr={1,4,3,2,7,5};
System.out.println(getnum(arr));
System.out.println(getnum1(arr));
}
}
6.如何找出数组中出现奇数次的数
题目描述:
数组中有N+2个数,其中,N个数出现了偶数次,两个数出现了奇数次(这两个数不相等),请用O(1)的空间复杂度,找出这两个数。注意:不需要知道具体位置,只需要找出这两个数。
package array;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class UnevenArray {
public static void get2Num(int[] arr){
if(arr==null||arr.length<1){
System.out.println("参数不合理");
return;
}
HashMap<Integer,Integer> map=new HashMap<>();
int i;
for(i=0;i<arr.length;i++){//map中没有整个数字,说明第一次出现,value赋值为1
if(!map.containsKey(arr[i])){
map.put(arr[i],1 );
//当前遍历的值在map中存在,说明前面出现过,value赋值为0
}else {
map.put(arr[i],0 );
}
}
Iterator<Map.Entry<Integer,Integer>>iter=map.entrySet().iterator();
while (iter.hasNext()){
Map.Entry<Integer,Integer>entry=(Map.Entry<Integer, Integer>) iter.next();
if(entry.getValue()==1)
System.out.println(entry.getKey());
}
}
//异或法
public static void get1Num(int[] arr) {
if(arr==null||arr.length<1){
System.out.println("参数不合理");
return;
}
int result=0;
int position=0;
//计算数组中所有数字异或的结果
for(int i=0;i< arr.length;i++){
result=result^arr[i];
}
int tmpResult=result;//临时保存异或结果
//找出异或结果中其中一个位置为1的位数(如1100,位置为1位数为2和3)
for (int i=result;(i&1)==0;i=i>>1){
position++;
}
for(int i=0;i< arr.length;i++){
//异或的结果与所有第position位为1的数异或,结果一定是出现两个数其中一个
if(((arr[i]>>position)&1)==1){
result=result^arr[i];
}
}
System.out.println(result);
//得到另一个出现一次的数
System.out.println(result^tmpResult);
}
public static void main(String[] args) {
int[] arr={3,5,6,6,5,7,2,2};
get2Num(arr);
}
}
7.如何找出数组中第K小的数
题目描述:
给定一个整数数组,如何快速地求出该数组中第k小的数。假如数组为{4,0,1,0,2,3},那么第三小的元素是1。部分排序法
package queue;
//类快速排序方法
public class Findsoft {
//在数组array中找到第k小的值
public static int findSmallk(int[] array ,int low,int high,int k){
int i,j;
int splitElem;
i=low;
j=high;
splitElem=array[i];
//把小于等于splitElem的数放到数组中splitElem的左边,大于spliElem的值放到右边
while (i<j){
while (i<j&&array[i]>=splitElem)
j--;
if(i<j)
array[i++]=array[j];
while (i<j&&array[i]<=splitElem)
i++;
if(i<j)
array[j--]=array[i];
}
array[i]=splitElem;
// splitElem 在子数组array[low~high]中下标的偏移量
int subArrayIndex=i-low;
// splitElem 在array[low~high]所在的位置恰好为k-1,那么它就是第k小的元素
if(subArrayIndex==k-1)
return array[i];
else if(subArrayIndex>k-1)
return findSmallk(array, low, i-1, k);
// 在array[i+1~high]中找第k-i+low-1小的元素
else
return findSmallk(array,i+1, high, k-(i-low)-1);
}
public static void main(String[] args) {
int k=3;
int[] array={4,0,1,2,3};
System.out.println("第"+k+"小的值为:"+findSmallk(array,0,array.length-1,k));
}
}
8.如何求数组中两个元素的最小距离
题目描述:
给定一个数组,数组中含有重复元素,给定两个数字num1和num2,求这两个数字在数组中出现的位置的最小距离。
package array;
public class FindArray {
//动态规划
public static int minDistance(int [] arr,int num1,int num2){
if(arr==null||arr.length<=0){
System.out.println("参数不合理");
return Integer.MAX_VALUE;
}
int lastPos1=-1; //上次遍历到num1的位置
int lastPos2=-1;//上次遍历到num2的位置
int minDis=Integer.MAX_VALUE;//num1与num2的最小距离
for(int i=0;i< arr.length;i++){
if(arr[i]==num1){
lastPos1=i;
if(lastPos2>=0)
minDis=Math.min(minDis,lastPos1-lastPos2);
}
if(arr[i]==num2){
lastPos2=i;
if(lastPos1>=0)
minDis=Math.min(minDis,lastPos2-lastPos1);
}
}
return minDis;
}
public static void main(String[] args) {
int[]arr={4,5,6,7,4,6,4,7,8,5,6,4,3,10,8};
int num1=4;
int num2=8;
System.out.println(minDistance(arr,num1,num2));
}
}
9.如何求解最小三元 组距离
题目描述:
已知三个升序整数数组a[l]、b[m]和c[n],在三个数组中各找一个元素,使得组成的三元组距离最小。三元组距离的定义:假设a[i]、b[j]和c[k]是一个三元组,那么距离为:Distance=max(|a[i]-b[j]|,|a[i]-c[k]|,|b[j]-c[k]|),设计一个求最小三元组距离的最优算法。
public class Distancearray {
//最小距离法
public static int min(int a,int b ,int c){
int min=a<b?a:b;
min=min<c?min:c;
return min;
}
public static int max(int a,int b ,int c){
int max=a<b?b:a;
max=max<c?c:max;
return max;
}
public static int minDistance(int[] a,int[] b,int[] c){
int aLen=a.length;
int bLen=b.length;
int cLen=c.length;
int curDist=0;
int min=0;
int minDist=Integer.MAX_VALUE;
int i=0;//数组a的下标
int j=0;//数组b的下标
int k=0;//数组c的下标
while (true){
// Math.abs 返回绝对值
curDist=max(Math.abs(a[i]-b[j]),Math.abs(a[i]-c[k]),Math.abs(b[j]-c[k]));
if(curDist<minDist)
minDist=curDist;
//找出当前遍历到三个数组中的最小值
min=min(a[i],b[j],c[k]);
if(min==a[i]){
if(++i>=aLen)
break;
}else if(min==b[j]){
if(++j>=bLen)
break;
}else {
if(++k>=cLen)
break;
}
}
return minDist;
}
public static void main(String[] args) {
int[] a={3,4,5,7,15};
int[] b={10,12,14,16,17};
int[] c={20,21,23,24,37,30};
System.out.println("最小距离为:"+minDistance(a,b,c));
}
}
10.如何求数组中绝对值最小的数
题目描述:
有一个升序排列的数组,数组中可能有正数、负数或 0,求数组中元素的绝对值最小的数。例如,数组{-10,-5,-2, 7, 15, 50},该数组中绝对值最小的数是-2。
package array;
public class SabArray {
public static int findMin(int[] array){
if(array==null||array.length<=0){
System.out.println("输入参数");
return 0;
}
int len= array.length;
//数组中没有负数
if(array[0]>=0)
return array[0];
//数组中没有正数
if(array[len-1]<=0)
return array[len-1];
int mid=0;
int begin=0;
int end=len-1;
int absMin=0;
//数组中既有正数又有负数
while (true){
mid=begin+(end-begin)/2;
//如果等于0那么绝对值最小的数
if(array[mid]==0){
return 0;
//如果大于0,正负数的分界线在左侧
}else if(array[mid]>0){
//继续在数组的左半部查找
if(array[mid-1]>0)
end=mid-1;
else if(array[mid-1]==0)
return 0;
//找出正负数的分界线
else
break;
}else{//如果小于0,在数组右半部分查找
if(array[mid+1]<0)
begin=mid+1;
else if(array[mid+1]==0)
return 0;
//找出正负数分界线
else
break;
}
}
//获取正负数分界点出绝对值最小的值
if(array[mid]>0){
if(array[mid]<Math.abs(array[mid-1]))
absMin=array[mid];
else
absMin=array[mid-1];
}else {
if(Math.abs(array[mid])<array[mid+1])
absMin=array[mid];
else
absMin=array[mid+1];
}
return absMin;
}
public static void main(String[] args) {
int arr[] ={-10,-5,-2,7,15,50};
System.out.println("绝对值最小的数为"+findMin(arr));
}
}