题目及测试用例
package pid217;
/*存在重复
给定一个整数数组,判断是否存在重复元素。
如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。
示例 1:
输入: [1,2,3,1]
输出: true
示例 2:
输入: [1,2,3,4]
输出: false
示例 3:
输入: [1,1,1,3,3,4,3,2,4,2]
输出: true
*/
public class main {
public static void main(String[] args) {
int[][] testTable = {{1,2,3,1},{1,2,3,4},{1,1,1,3,3,4,3,2,4,2},{1,6,2,7,1}};
for (int[] ito : testTable) {
test(ito);
}
}
private static void test(int[] ito) {
Solution solution = new Solution();
boolean rtn;
long begin = System.currentTimeMillis();
for (int i = 0; i < ito.length; i++) {
System.out.print(ito[i]+" ");
}
System.out.println();
//开始时打印数组
rtn = solution.containsDuplicate(ito);//执行程序
long end = System.currentTimeMillis();
//System.out.println(ito + ": rtn=" + rtn);
System.out.println(ito + ": rtn=" +rtn);
// for (int i = 0; i < ito.length; i++) {
// System.out.print(ito[i]+" ");
// }//打印结果几数组
System.out.println();
System.out.println("耗时:" + (end - begin) + "ms");
System.out.println("-------------------");
}
}
解法1(部分成功,最后一个超时)
超级缓慢的解法,一个一个查是否重复
package pid217;
public class Solution {
public boolean containsDuplicate(int[] nums) {
int length=nums.length;
if(length==0||length==1)
return false;
for(int i=1;i<length;i++){
int now=nums[i];
for(int j=0;j<i;j++){
if(now==nums[j]){
return true;
}
}
}
return false;
}
}
解法2(部分成功,最后一个超时,采用快排的思想,找到则返回)
查看最后一个测试用例,有27万个数字
class Solution {
public static boolean isDuplicate=false;
public boolean containsDuplicate(int[] nums) {
isDuplicate=false;
int length=nums.length;
if(length==0||length==1)
return false;
fastSortDuplicate(nums,0,length-1);
return isDuplicate;
}
private void fastSortDuplicate(int[] nums,int begin,int last) {
if(isDuplicate==true){
return;
}
int length=nums.length;
if(length==0||length==1){
return;
}
int base=nums[begin];
int i=begin;
int j=last;
int mid=0;
//i为第一个,j为最后一个,base为第一个数字,此时i处为base
while(true){
//j从后往前找到比base小的数字,与i作颠倒,颠倒后j处为base,i处为之前j处比base小的数
while(j!=i){
if(nums[j]<base ){
nums[i]=nums[j];
nums[j]=base;
break;
}
else{
if(nums[j]==base ){
if(i==j){
mid=i;
break;
}
System.out.println(base);
System.out.println(j);
isDuplicate=true;
return;
}
else{
j--;
}
}
}
//如果上一个j过程结束,如果i与j相同,中间为i,跳出大过程
if(i==j){
mid=i;
break;
}
//i从后往前找到比base大的数字,与j作颠倒,颠倒后i处为base,j处为之前i处比base大的数,跳出这个小循环
i++;
while(i!=j){
if(nums[i]>base){
nums[j]=nums[i];
nums[i]=base;
break;
}
else{
if(nums[i]==base ){
if(i==j){
mid=i;
break;
}
System.out.println(base);
System.out.println(i);
isDuplicate=true;
return;
}
else{
i++;
}
}
}
//如果上一个i过程结束,如果i与j相同,中间为i,跳出大过程
if(i==j){
mid=i;
break;
}
}
//System.out.println(Arrays.toString(nums));
//从此处开始mid处为base,比mid处大的,则比base大,反之亦然
//对两次进行递归快速排序
if((mid-begin)>1){
fastSortDuplicate(nums, begin, mid-1);
}
if((last-mid)>1){
fastSortDuplicate(nums, mid+1, last);
}
return;
}
}
解法3(成功,24ms,比较快)
采用set的数据结构
public boolean containsDuplicate(int[] nums) {
int length=nums.length;
HashSet<Integer> set=new HashSet<>();
for(int i=0;i<length;i++){
if(set.contains(nums[i])){
return true;
}
set.add(nums[i]);
}
return false;
}
解法4(别人的,8ms很快)
使用计数排序的思想,创建一个新数组来计数
这个方法按道理,时间复杂度和set是一样的,还要遍历两次,但是之所以快,可能是hashset内部操作虽然是O(1),但是有几部操作,反而比计数排序每位总共只做三个操作慢
public boolean containsDuplicate(int[] nums) {
if (nums.length == 0) {
return false;
}
int min = nums[0];
int max = nums[0];
for (int i = 0; i < nums.length; i++) {
max = Math.max(max,nums[i]);
min = Math.min(min,nums[i]);
}
int d = max - min;
int[] arr = new int[d + 1];
for (int i = 0; i < nums.length; i++) {
arr[nums[i] - min]++;
if (arr[nums[i] - min] == 2) {
return true;
}
}
return false;
}