- 浏览: 2057161 次
- 性别:
- 来自: 北京
-
文章分类
- 全部博客 (795)
- java (263)
- 聚类搜索引擎 (9)
- 经验之谈 (67)
- DSP (3)
- C++ (140)
- Linux (37)
- SNMP (6)
- Python (6)
- 数据库 (61)
- 网络 (20)
- 算法 (15)
- 设计模式 (4)
- 笔试题 (38)
- 散文 (35)
- 数据结构 (9)
- 银行知识 (0)
- 榜样 (9)
- Lucene (15)
- Heritrix (6)
- MetaSeeker (0)
- netbeans (12)
- php (3)
- 英语 (8)
- DB2 (0)
- java基础 (5)
- mongodb & hadoop (4)
- Javascript (7)
- Spring (4)
- ibatis & myibatis (1)
- velocity (1)
- 微服务 (0)
- paddle (1)
- 第三方 (0)
- 知识沉淀 (1)
- 建模 (0)
最新评论
-
0372:
标示对java很陌生!
中文乱码解决的4种方式 -
梦留心痕:
Java中\是转意字符, 可是你的这句话我没看懂,只要把得到的 ...
java中如何忽略字符串中的转义字符--转载 -
yanjianpengit:
[b][/b]
java为什么非静态内部类里面不能有静态成员 -
springdata-jpa:
可以参考最新的文档:如何在eclipse jee中检出项目并转 ...
eclipse 如何把java项目转成web项目 -
qq1130127172:
,非常好。
(转)SpringMVC 基于注解的Controller @RequestMapping @RequestParam..
题目是这样的, 数组是无序的, 可能没有重复的数,但最多只可能有一个重复的数,要求用最快的方法找到是否有重复的数。
乍一想,挺难的,但是其实非常的简单。
解决办法:
数组a[N],1至N-1这N-1个数存放在a[N]中,其中某个数重复一次。写一个函数,找出被重复的数字。时间复杂度必须为o(N)函数原型:
int do_dup(int a[],int N)
××××××××××××××××××××××××××××××××××
假金条的数学思想
此算法题借鉴了假金条的思想,不过比那个过程简单,存放1至N-1,就相当于依次从各个袋中取出1至N-1个金条,但是有一个是重的,计算这N个数的和将相当于称总重量,减去1至N-1的和(用数学方法求)就可求出来重复的数。总之要充分利用数学知识
const int N = 5;
int a[N]={2,1,3,1,4};
int tmp1 = 0;
int tmp2 = 0;
for (int i=0; i<N; ++i)
{
tmp1+=(i+1);
tmp2+=a[i];
}
printf("重复的数:%d\n",N-(tmp1-tmp2));
上述方法求1~N的和,减去数组总和,即为N-x 的差值,x为待找的数
可以优化的是1-N的和不用程序算,数学方法直接算了
可定义一个宏,
#define sum(x) (x(x+1)/2)
当然乘法操作是比较复杂的,当N较小时加几个数的效率可能更高
××××××××××××××××××××××××××××××××××
标志数组法
申请一个长度为n-1且均为'0'组成的字符串。然后从头遍历a[n]数组,取每个数组元素a[i]的值,将其对应的字符串中的相应位置置1,如果已经置过1的话,那么该数就是重复的数。就是用位图来实现的。
其实,只要数还是0 -- n-1里面的数,那么可以用这样的方法判断所有的重复数的位置和值。
比如这样的一个数组
{2,3,1,2}
我们生成一个字符串"000";
然后开始遍历,a[0] = 2;
所以,字符串的第二位为"0",那么我们将其置为"1"
字符串为"010"
重复,字符串为"011",,,,,"111"
然后,判断a[3] = 2 那么 第二位为"1"
所以,a[3]为重复数,并且位置为第4位。
上述map等各方法的思路是一致的,即访问过后做标记,再次访问时即可知道是否重复。如果考虑空间复杂度的话,其空间o(N)
int do_dup(int arr[],int NUM)
{
int *arrayflag = malloc(NUM*sizeof(int));
while(i++<NUM)
arrayflag[i] = false;
for(int i=0; i<NUM; i++)
{
if(arrayflag[arr[i]] >= false)
arrayflag[arr[i]] >= true; // 置出现标志
else
return arr[i]; //返回已经出现的值
}
}
××××××××××××××××××××××××××××××××××
固定偏移标志法
利用标记法单纯写个O(N)的方法并不难,关键是如何保证两点:
不改变A[]的初始值
函数内不开辟另外的O(N)内存空间.
很明显上述方法申请了O(N)内存空间,当N过大时,性能降低了
因此应利用a[N]本身中值和下标的关系来做标记,处理完成后再清除标记即可
a[N],里面是1至N-1。原数组a[i]最大是N-1,若a[i]=K在某处出现后,将a[K]加一次N,做标记,当某处a[i]=K再次成立时,查看a[K]即可知道K已经出现过。a[i]在程序中最大也只是N-1+N=2N-1(溢出了怎么办啊???),此为一个限制条件
int do_dup(int arr[],int NUM)
{
int temp=0;
for(int i=0; i<NUM; i++)
{
if(arr[i]>=NUM)
temp=arr[i]-NUM; // 该值重复了,因为曾经加过一次了
else
temp=arr[i];
if(arr[temp]<NUM)
{
arr[temp]+=NUM; //做上标记
}
else
{
printf("有重复");
return temp;
}
}
printf("无重复");
return -1;
}
上面就是时间复杂度O(N), 空间复杂度O(1)的算法!
××××××××××××××××××××××××××××××××××
符号标志法
上述方法将元素加一个固定的NUM来做标记,可能会造成溢出。下列方法中利用符号位来做标记,因为1~N都为正值,所以就无限制了。基本思想是用int数组的符号位作哈希表。(反正不是unsigned int符号位闲着也是闲着)
bool dup(int array[],int n)
{
for(int i=0;i<n;i++)
{
if(array[i]>0) //可以以此作下标去判断其他值
{
if(array[array[i]]<0)
{
return array[i];//已经被标上负值了,有重复
}
else
{
array[array[i]]= -array[array[i]]; //否则标记为负
}
}
else // |array[i]|代表的值已经出现过一次了
{
if(array[-array[i]]<0)
{
return -array[i];//有重复
}
else
{
array[-array[i]]=-array[-array[i]];
}
}
}
return -1;//没有重复
}
//用于修复数组
void restorearray(int array[],int n)
{
for(int i=0;i<n;i++)
{
if(array[i]<0)array[i]= -array[i];
}
}
时间复杂度o(n) 空间复杂度o(1)
不过时间复杂度o(n) 空间复杂度o(1)不只一个重复利用此法也是可以实现的
//附上我修改后的算法
bool do_dup_mal(int arr[], int n, int *pre, int *back)
{
int MAX = -1;
int i = 0;
int sameVal = -1;
assert(pre && back);
*pre = *back = -1;
for (int j=0; j<n; j++)
{
if (arr[j] > MAX) MAX = arr[j];
}
char *arrayflag = new char[MAX+1] ;
if (NULL == arrayflag)
return -1;
//while(i++ < MAX) arrayflag[i] = '\0';
memset(arrayflag, 0, MAX+1 ); // '\0' == 0
for(i=0; i<n; i++)
{
if(arrayflag[arr[i]] == '\0')
arrayflag[arr[i]] = '\1'; // 置出现标志
else
{
sameVal = arr[i]; //返回已经出现的值
*back = i;
break;
}
}
delete[] arrayflag;
if (i < n)
{
for (int j=0; j<n; j++)
{
if (sameVal == arr[j])
{
*pre = j;
return true;
}
}
}
return false;
}
int main(int argc, char *argv[])
{
int prePos = -1, backPos = -1;
int myArry[N];
myArry[0] = 1;
myArry[1] = 23;
myArry[2] = 3;
myArry[3] = 4;
myArry[4] = 5;
myArry[5] = 22;
myArry[6] = 7;
myArry[7] = 8;
myArry[8] = 9;
myArry[9] = 22;
myArry[10] = 12;
if (do_dup_mal(myArry, 11, &prePos, &backPos) )
printf("\nT
乍一想,挺难的,但是其实非常的简单。
解决办法:
数组a[N],1至N-1这N-1个数存放在a[N]中,其中某个数重复一次。写一个函数,找出被重复的数字。时间复杂度必须为o(N)函数原型:
int do_dup(int a[],int N)
××××××××××××××××××××××××××××××××××
假金条的数学思想
此算法题借鉴了假金条的思想,不过比那个过程简单,存放1至N-1,就相当于依次从各个袋中取出1至N-1个金条,但是有一个是重的,计算这N个数的和将相当于称总重量,减去1至N-1的和(用数学方法求)就可求出来重复的数。总之要充分利用数学知识
const int N = 5;
int a[N]={2,1,3,1,4};
int tmp1 = 0;
int tmp2 = 0;
for (int i=0; i<N; ++i)
{
tmp1+=(i+1);
tmp2+=a[i];
}
printf("重复的数:%d\n",N-(tmp1-tmp2));
上述方法求1~N的和,减去数组总和,即为N-x 的差值,x为待找的数
可以优化的是1-N的和不用程序算,数学方法直接算了
可定义一个宏,
#define sum(x) (x(x+1)/2)
当然乘法操作是比较复杂的,当N较小时加几个数的效率可能更高
××××××××××××××××××××××××××××××××××
标志数组法
申请一个长度为n-1且均为'0'组成的字符串。然后从头遍历a[n]数组,取每个数组元素a[i]的值,将其对应的字符串中的相应位置置1,如果已经置过1的话,那么该数就是重复的数。就是用位图来实现的。
其实,只要数还是0 -- n-1里面的数,那么可以用这样的方法判断所有的重复数的位置和值。
比如这样的一个数组
{2,3,1,2}
我们生成一个字符串"000";
然后开始遍历,a[0] = 2;
所以,字符串的第二位为"0",那么我们将其置为"1"
字符串为"010"
重复,字符串为"011",,,,,"111"
然后,判断a[3] = 2 那么 第二位为"1"
所以,a[3]为重复数,并且位置为第4位。
上述map等各方法的思路是一致的,即访问过后做标记,再次访问时即可知道是否重复。如果考虑空间复杂度的话,其空间o(N)
int do_dup(int arr[],int NUM)
{
int *arrayflag = malloc(NUM*sizeof(int));
while(i++<NUM)
arrayflag[i] = false;
for(int i=0; i<NUM; i++)
{
if(arrayflag[arr[i]] >= false)
arrayflag[arr[i]] >= true; // 置出现标志
else
return arr[i]; //返回已经出现的值
}
}
××××××××××××××××××××××××××××××××××
固定偏移标志法
利用标记法单纯写个O(N)的方法并不难,关键是如何保证两点:
不改变A[]的初始值
函数内不开辟另外的O(N)内存空间.
很明显上述方法申请了O(N)内存空间,当N过大时,性能降低了
因此应利用a[N]本身中值和下标的关系来做标记,处理完成后再清除标记即可
a[N],里面是1至N-1。原数组a[i]最大是N-1,若a[i]=K在某处出现后,将a[K]加一次N,做标记,当某处a[i]=K再次成立时,查看a[K]即可知道K已经出现过。a[i]在程序中最大也只是N-1+N=2N-1(溢出了怎么办啊???),此为一个限制条件
int do_dup(int arr[],int NUM)
{
int temp=0;
for(int i=0; i<NUM; i++)
{
if(arr[i]>=NUM)
temp=arr[i]-NUM; // 该值重复了,因为曾经加过一次了
else
temp=arr[i];
if(arr[temp]<NUM)
{
arr[temp]+=NUM; //做上标记
}
else
{
printf("有重复");
return temp;
}
}
printf("无重复");
return -1;
}
上面就是时间复杂度O(N), 空间复杂度O(1)的算法!
××××××××××××××××××××××××××××××××××
符号标志法
上述方法将元素加一个固定的NUM来做标记,可能会造成溢出。下列方法中利用符号位来做标记,因为1~N都为正值,所以就无限制了。基本思想是用int数组的符号位作哈希表。(反正不是unsigned int符号位闲着也是闲着)
bool dup(int array[],int n)
{
for(int i=0;i<n;i++)
{
if(array[i]>0) //可以以此作下标去判断其他值
{
if(array[array[i]]<0)
{
return array[i];//已经被标上负值了,有重复
}
else
{
array[array[i]]= -array[array[i]]; //否则标记为负
}
}
else // |array[i]|代表的值已经出现过一次了
{
if(array[-array[i]]<0)
{
return -array[i];//有重复
}
else
{
array[-array[i]]=-array[-array[i]];
}
}
}
return -1;//没有重复
}
//用于修复数组
void restorearray(int array[],int n)
{
for(int i=0;i<n;i++)
{
if(array[i]<0)array[i]= -array[i];
}
}
时间复杂度o(n) 空间复杂度o(1)
不过时间复杂度o(n) 空间复杂度o(1)不只一个重复利用此法也是可以实现的
//附上我修改后的算法
bool do_dup_mal(int arr[], int n, int *pre, int *back)
{
int MAX = -1;
int i = 0;
int sameVal = -1;
assert(pre && back);
*pre = *back = -1;
for (int j=0; j<n; j++)
{
if (arr[j] > MAX) MAX = arr[j];
}
char *arrayflag = new char[MAX+1] ;
if (NULL == arrayflag)
return -1;
//while(i++ < MAX) arrayflag[i] = '\0';
memset(arrayflag, 0, MAX+1 ); // '\0' == 0
for(i=0; i<n; i++)
{
if(arrayflag[arr[i]] == '\0')
arrayflag[arr[i]] = '\1'; // 置出现标志
else
{
sameVal = arr[i]; //返回已经出现的值
*back = i;
break;
}
}
delete[] arrayflag;
if (i < n)
{
for (int j=0; j<n; j++)
{
if (sameVal == arr[j])
{
*pre = j;
return true;
}
}
}
return false;
}
int main(int argc, char *argv[])
{
int prePos = -1, backPos = -1;
int myArry[N];
myArry[0] = 1;
myArry[1] = 23;
myArry[2] = 3;
myArry[3] = 4;
myArry[4] = 5;
myArry[5] = 22;
myArry[6] = 7;
myArry[7] = 8;
myArry[8] = 9;
myArry[9] = 22;
myArry[10] = 12;
if (do_dup_mal(myArry, 11, &prePos, &backPos) )
printf("\nT
发表评论
-
DLL中导出函数的声明有两种方式:
2012-11-12 16:42 1894DLL中导出函数的声明有两种方式: 一种方式是:在函数声明中 ... -
k-means算法的C++实现
2011-04-05 11:38 2358k-means算法的C++实现: http://www.ku ... -
main()中的参数
2010-10-31 10:41 1552所有的应用程序都是从以main函数作为入口, 而mai ... -
static作用
2010-10-26 19:15 2415转自(from http://www.cnb ... -
mmap函数
2010-10-25 22:41 1933mmap函数的使用方法 UNIX ... -
C语言中三种内存分配方式
2010-10-25 20:23 01.malloc 原型:extern void *ma ... -
位拷贝和值拷贝
2010-10-23 15:37 1616为了便于说明我们以String类为例: 首先定义String ... -
(转帖)把类的析构函数写成虚函数的用意
2010-10-23 15:10 1715#include <iostream.h> cl ... -
动态规划/贪心算法----0/1背包问题AND普通背包问题
2010-10-23 14:03 6842两个背包问题都是比较典型的问题,对这两种算法的理解有很好的帮助 ... -
netstat, nslookup, finger, ping命令
2010-10-22 17:13 1565Netstat用于显示与IP、TCP ... -
C++返回值
2010-10-22 16:53 1594C++函数返回值: (1)正常情况下,函数的参数要复制一份在 ... -
switch语句后的表达式的值
2010-10-22 16:23 1859一般格式: switch (表达式) { case 常量 ... -
C++四种强制类型转换
2010-10-19 11:45 1588显式类型转换又被称之 ... -
C++四种强制类型转化的区别
2010-10-19 11:43 1370先介绍const_cast和reinterpret_cast: ... -
Visual C++线程同步技术剖析:临界区,时间,信号量,互斥量
2010-10-18 14:24 1845使线程同步 在程序中使用多线程时,一般很少有多个线程能在其 ... -
(转)临界区,互斥量,信号量,事件的区别
2010-10-18 14:22 1786四种进程或线程同步互斥的控制方法1、临界区:通过对多线程的串行 ... -
(转)在C++中实现同步锁,类似synchronize(object){....}
2010-10-18 13:49 1899在做C++的项目中发现, ... -
C++线程同步
2010-10-18 13:46 1637线程同步是多 ... -
C++多线程编程
2010-10-18 10:56 1767今天我给大家讲一讲C++ ... -
关于C++对函数传参与函数返回值进行引用传递的详解
2010-10-16 22:51 4077关于C++对函数传参与函数返回值进行引用传递的详解 ...
相关推荐
剑指offer面试题库中第三题的C语言代码。在一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
Java找出数组中重复的数字 本文主要是介绍了Java语言中如何找出数组中重复的数字。该问题是剑指offer中的经典面试题,旨在考察程序员的编程能力和算法思维。 问题描述 在一个长度为n的数组里的所有数字都在0~n-1...
本文实例讲述了C语言查找数组里数字重复次数的方法。分享给大家供大家参考。具体如下: #include stdafx.h #include #include using namespace std; int main() { int myarray[10]={4,3,7,4,8,7,9,4,3,6}; ...
找出数组中重复的数字。在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
找出数组中重复的数字.md
网上那种找出两个数组重复元素的代码复杂度较高,这个比较简单,一次循环搞定
"Java 剑指offer(1) 找出数组中重复的数字" 本资源为Java语言编写,旨在解决数组中重复数字的问题。该问题描述为:在一个长度为n的数组里的所有数字都在0到n-1的范围内,数组中某些数字是重复的,但不知道有几个...
1. **查找重复元素**:在LabVIEW中,可以通过比较数组中的每一个元素与其余元素来找出重复项。这可以通过循环结构(例如For Loop或While Loop)配合条件判断(如Relational Operator VI)来实现。对于大数组,使用...
在编程领域,处理数组是常见的任务之一,尤其是在...通过这样的方法,我们能够有效地找出数组中重复文本的下标,并根据需要去除这些重复的元素。在易语言中,理解和运用这些技巧将有助于编写更加高效和实用的程序。
// 找出所有重复的ID及其位置 for (int i = 0; i ; ++i) { for (int j = i + 1; j ; ++j) { if (irand[i] == irand[j]) { tempOld.push_back(i); break; } } } // 生成新的未使用的ID for (int i = 0; i...
在本问题中,我们面临的是一个经典的算法挑战:找出数组中三个数字的组合,使得它们的和为零。这个题目属于计算机科学中的“三数之和”问题,通常在算法设计和面试中出现,旨在考察候选人的逻辑思维和解决复杂问题的...
找出数组中重复元素的下标,通常需要遍历数组,对比当前元素与其他元素是否相同。以下是一个简单的伪代码示例: 1. 初始化一个空的哈希表(或字典)来存储元素及其出现的索引。 2. 遍历数组,对于每个元素: - ...
这个源码的目的是找出数组中相同的文本元素,并返回它们在数组中的下标。 实现这个功能通常需要以下步骤: 1. 定义一个包含文本的数组。 2. 遍历数组,对于每个元素,检查它是否已经存在于已找到的重复元素列表中。...
在给定的编程问题“1、数组中重复的数字(Python)”中,目标是找出一个整数数组中任意一个重复的数字。数组的长度为 n,并且数组内的所有元素都在 0 到 n-1 的范围内。由于题目并未要求找出所有的重复数字,只需要...
本篇文章将深入探讨如何编写源代码来找出两个数组中的相同元素,并显示它们在数组中的位置。我们将基于标题和描述提供的信息,详细讲解实现这一功能的关键步骤和相关知识点。 首先,我们需要创建两个数组,分别存储...
请找出数组中任意一个重复的数字。 示例 : 输入: [2, 3, 1, 0, 2, 5, 3] 输出:2 或 3 复制 思路分析 首先想到的是暴力法—两个for循环实现,缺点很明显:用时过多。再进一步可以先排序数组然后一次for循环,...
然而,在处理数组时,一个常见的需求是检查数组中是否存在重复的元素,这对于数据校验、排序算法、去重操作等场景至关重要。 ### C#验证数组元素是否重复的知识点 #### 1. 数组的定义与初始化 在C#中,数组可以...
问题要求在一个已知范围内的整数数组中,找出任意一个重复的数字,而不需要知道重复的次数。 给定的示例输入为 `[2, 3, 1, 0, 2, 5, 3]`,期望的输出是 `2` 或 `3`,因为这两个数字在数组中出现了不止一次。 提供...
JS查找数组中重复元素的方法详解: 首先,本文主要介绍了在JavaScript中如何查找数组内的重复元素。查找重复元素是一个常见的编程任务,尤其在数据处理和分析中尤为重要。JavaScript提供了灵活的数组操作API,可以...
请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3. 解法1:对于数组进行排序,之后对于已经排序的数组进行遍历便可知道数组中重复的数字。 时间...