添加剑指 Offer 题目[数组中重复数字]

This commit is contained in:
Zhoust 2019-05-01 12:10:29 +08:00
parent 4e3b7d0be3
commit 881a7fe121
2 changed files with 154 additions and 0 deletions

View File

@ -0,0 +1,147 @@
package com.pancm.arithmetic.jzoffer;
/**
* https://www.nowcoder.com/practice/623a5ac0ea5b4e5f95552655361ae0a8?tpId=13&tqId=11203&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
*
* @description:
* 3.数组中的重复数字
* 在一个长度为 n 的数组里的所有数字都在 0 n-1 的范围内
* 数组中某些数字是重复的但不知道有几个数字是重复的也不知道每个数字重复几次
* 请找出数组中任意一个重复的数字
*
* @author: Zhoust
* @date: 2019/04/28 10:58
* @version: V1.0
*/
public class DuplicateNumberInArray {
/**
* 一种简单的实现思路借助外部数组保存 numbers 中每个值的出现次数 numbers 中的值作为数组 array 的下标
* 题目中说了长度为 n 的数组中每个值都在 0 n-1 范围内因此遍历数组 numbers 存入对应的 array 不会出现数组下标越界的问题
* @param numbers
* @param length numbers 数组的长度
* @param duplication (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
* 这里要特别注意~返回任意重复的一个赋值duplication[0]
* @return true if the input is valid, and there are some duplications in the array number, otherwise false
*/
public boolean duplicate(int[] numbers, int length, int[] duplication) {
if (numbers == null) {
return false;
}
boolean result = false;
int[] array = new int[length];
for (int i = 0; i < length; i++) {
if (++array[numbers[i]] > 1 && !result) {
result = true;
duplication[0] = numbers[i];
}
}
return result;
}
/**
* 先排序然后找到排序后数组中第一个重复的数字主要就是练习一下快排
* @param numbers
* @param length
* @param duplication
* @return
*/
public boolean sortThenFindFirstDuplicateNumber(int[] numbers, int length, int[] duplication) {
if (numbers == null) {
return false;
}
quickSort(numbers, 0, length-1);
int temp = numbers[0];
boolean result = false;
for (int i = 1; i < length; i++) {
if (numbers[i] == temp) {
result = true;
duplication[0] = temp;
break;
}
temp = numbers[i];
}
return result;
}
/**
* 将值为 i 的元素调整到下标为 i 的位置如果该位置上的数已经等于 i 就说明 i 已经重复了
* @param numbers
* @param length
* @param duplication
* @return
*/
public static boolean jz(int[] numbers, int length, int[] duplication) {
for (int i = 0; i < length; i++) {
// i 个位置上的数 numbers[i] 若不与下标 i 相等就把 numbers[i] 放到下标为 numbers[i] 的位置
while (numbers[i] != i) {
//在交换位置之前还要检查 numbers[i] 位置上的数字是否已经是 numbers[i]如果是就已经找到了重复的数字
if (numbers[numbers[i]] == numbers[i]) {
duplication[0] = numbers[i];
//注意这里不是 break
return true;
}
//交换下标为 inumbers[i] 两个位置上的数字保证下标为 numbers[i] 的位置放置的数字是 numbers[i]
swap(numbers, i, numbers[i]);
}
}
return false;
}
/**
* 交换下标为 ij 的两个数
* @param numbers
* @param i
* @param j
*/
public static void swap(int[] numbers, int i, int j) {
int swap = numbers[i];
numbers[i] = numbers[j];
numbers[j] = swap;
}
/**
* 快排
* @param array
* @param length
*/
@SuppressWarnings("all")
public static void quickSort(int[] array, int low, int high) {
//这里必须首先限制 low<high否则会出现 ArrayIndexOutOfBoundsException
if (low < high) {
int temp = array[low];
int l = low, h = high;
while (l != h) {
while (array[h] > temp && h > l) {
h--;
}
array[l] = array[h];
while (array[l] <= temp && l < h) {
l++;
}
array[h] = array[l];
}
array[l] = temp;
quickSort(array, low, h-1);
quickSort(array, l+1, high);
}
}
public static void main(String[] args) {
int[] result = new int[1];
jz(new int[]{2,4,2,1,4}, 5, result);
System.out.println(result[0]);
// int[] d = new int[1];
// jz(new int[]{2,1,3,0,4}, 5, d);
// int[] array = new int[]{1,4,4,4,12,78,8,45,67,39,20,90,65,34,34,6,7,88,9,1,-3,-88,-2};
int[] array = new int[]{2,4,3,1,4};
quickSort(array, 0, array.length-1);
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}

View File

@ -0,0 +1,7 @@
/**
* @description: 剑指 Offer 中的题目
* @author: Zhoust
* @date: 2019/04/28 10:57
* @version: V1.0
*/
package com.pancm.arithmetic.jzoffer;