# Java实现关于数组的一些骚操作

## 如何找出数组中唯一的重复元素？

    public static int findDump(int[] a){
if (a == null || a.length == 0)
return Integer.MAX_VALUE;
int sumA = 0;
int sumN = 0;
for (int i = 0; i < a.length-1; i++) {
sumA += a[i];
sumN += (i+1);
}
sumA += a[a.length-1];
return sumA - sumN;
}

（1-N-1，A）^(1-N-1) = A

   public static int findDumpWithSpace1(int[] a){
if (a == null || a.length == 0)
return Integer.MAX_VALUE;
int result = 0;
for (int i = 0; i < a.length; i++) {
result ^= a[i];
}
for (int i = 1; i < a.length; i++) {
result ^= i;
}
return result;
}

    public static int findDumpWithSpace2(int[] a){
if (a == null || a.length == 0)
return Integer.MAX_VALUE;
int n = a.length;
int[] appear = new int[n];
for (int i = 0; i < n; i++) {
int curr = a[i];
if (appear[curr] == 1)
return curr;
else
appear[curr] ++;
}
return Integer.MAX_VALUE;
}

## 如何用递归求得数组中的最大值？

    public static int findMaxNumRecursive(int[] a,int k){
if (k == a.length -1)
return a[k];
int curr = findMaxNumRecursive(a,k+1);
return Math.max(curr,a[k]);
}

# 如何求数对之差的绝对值？

    public static int getMaxSub1(int[] a){
if (a == null || a.length == 0)
return Integer.MAX_VALUE;
int max = 0;
int len = a.length;
for (int i = 0; i < len; i++) {
for (int j = i+1; j < len; j++) {
int diff = a[i] - a[j];
max = Math.max(max,diff);
}
}
return max;
}

    public static int getMaxSub2(int[] a){
if (a == null || a.length == 0)
return Integer.MAX_VALUE;
int len = a.length;
int[] diff = new int[len];
int[] max = new int[len];
diff[0] = 0;
max[0] = a[0];
for (int i = 1; i < len; i++) {
diff[i] = Math.max(diff[i-1],max[i-1]-a[i]);
max[i] = Math.max(max[i-1],a[i]);
}
return diff[len-1];
}
//动态规划改进：无需数组，只需两个变量，记录上一个最大的差值和最大的数组记录
public static int getMaxSub3(int[] a){
if (a == null || a.length == 0)
return Integer.MAX_VALUE;
int len = a.length;
int diff = 0;
int max = a[0];
for (int i = 0; i < len; i++) {
diff = Math.max(diff,max-a[i]);
max = Math.max(max,a[i]);
}
return diff;
}

# 如何求绝对值最小的数？

    public static int getMinAbsoluteValue(int[] a) {
if (a == null || a.length == 0)
return Integer.MAX_VALUE;
int len = a.length;
if (a[0] >= 0)
return a[0];
if (a[len - 1] <= 0)
return a[len - 1];
int begin = 0;
int end = len-1;
int mid = 0;
while (true){
mid = (begin+end) >> 1;
if (a[mid] == 0)
return a[mid];
else if (a[mid] > 0){
if (mid > 0 && a[mid-1] == 0)
return a[mid-1];
else if (mid > 0 && a[mid-1] > 0){
end = mid-1;
}else   //找到正负分界点
break;
}else {
if (mid < len-1 && a[mid+1] == 0)
return a[mid+1];
else if (mid < len-1 && a[mid+1] < 0 )
begin = mid+1;
else  //找到正负分界点
break;
}
}
if (a[mid] > 0){
if (Math.abs(a[mid-1]) > a[mid])
return a[mid];
else
return a[mid-1];
}else{
if (Math.abs(a[mid]) > a[mid+1])
return a[mid+1];
else
return a[mid];
}
}

# 如何求数组中两个元素的最小距离？

①遇到n1时，记录n1对应的数组下标位置index1，通过求index1与上次遍历遇到n2的下标值index2的差，可以求出最近一次遍历到的n1与n2的距离
②遇到n2时，记录n2对应的数组下标的位置index2，然后通过求index2与上次遍历遇到n1的下标值index1的差，可以求出最近一次遍历到的n1与n2的距离

   public static int minDistance(int[] a,int n1,int n2){
if (a == null || a.length == 0)
return -1;
int len = a.length;
int index1 = -1;
int index2 = -1;
int minDis = Integer.MAX_VALUE;
for (int i = 0; i < len; i++) {
if (a[i] == n1){
index1 = i;
if (index2 > 0) {
minDis = Math.min(Math.abs(minDis), Math.abs(index1 - index2));
}
}
if (a[i] == n2){
index2 = i;
if (index1 > 0) {
minDis = Math.min(Math.abs(minDis), Math.abs(index1 - index2));
}
}
}
return minDis;
}

# 如何求指定数字在数组中第一次出现的位置？

    public static int findIndex(int[] a,int t){
if (a == null || a.length == 0)
return -1;
int len = a.length;
int i = 0;
while (i < len){
if (a[i] == t)
return i;
else {
i += Math.abs(t - a[i]);
}
}
return -1;
}

# 如何对数组的两个子有序段进行合并？

    public static void mergeTwoArrayWithNoSpace(int[] a,int mid){
if (a == null || a.length == 0 || mid < 0 || mid > a.length-1)
return;
for (int i = 0; i < mid; i++) {
if (a[mid] < a[i]){
int tmp = a[mid];
a[mid] = a[i];
a[i] = tmp;
findRightPlaceForMid(a,mid);
}
}
}
private static void findRightPlaceForMid(int[] a,int mid){
boolean flag = true;
for (int i = mid; i < a.length - 1 && flag; i++) {
flag = false;
if (a[i+1] < a[i]){
flag = true;
int tmp = a[i];
a[i] = a[i+1];
a[i+1] = tmp;
}
}
}

# 如何计算两个有序整数数组的交集？

• 长度相当的数组：

①依次从头遍历两个数组，遇到相同的则后移指针，如果其中一个记录大，则后移记录小的数组的指针，直到一个数组遍历结束

    public static ArrayList<Integer> Mixed1(int[] a1,int[] a2){
ArrayList<Integer> result = new ArrayList<>();
if (a1 == null || a2 == null || a1.length == 0 || a2.length == 0)
return result;
int index1 = 0;
int index2 = 0;
int len1 = a1.length;
int len2 = a2.length;
while (index1 < len1 && index2 < len2){
if (a1[index1] == a2[index2]){
index1++;
index2++;
}else if (a1[index1] < a2[index2])
index1++;
else
index2++;
}
return result;
}

②利用哈希表，先将一个数组中的记录保存在哈希表中，然后遍历另一个数组，判断其中的记录是否在哈希表中，如果在哈希表中则证明属于交集

    public static ArrayList<Integer> Mixed2(int[] a1,int[] a2){
ArrayList<Integer> result = new ArrayList<>();
if (a1 == null || a2 == null || a1.length == 0 || a2.length == 0)
return result;
Map<Integer,Integer> map = new HashMap<>();
for (int i = 0; i < a1.length; i++) {
map.put(a1[i],1);
}
for (int i = 0; i < a2.length; i++) {
if (map.containsKey(a2[i]))
}
return result;
}

③顺序遍历两个数组，保存记录及其数量到哈希表中，如果出现的次数为2则是交集中的元素

06-12 1351

03-14 101
04-01 594
03-23 4888
05-10 55
10-23 1003
03-20 73