文章目录
题目:
定义一个int型的一维数组,包含10个元素,用随机整数初始化。
生成随机数
0…9
int tmp=(int) (Math.random()*10);//[0.0,1.0) 强转 注意优先级(后面*10要带括号)
//int tmp=new Random().nextInt(10);//[0,9)
1…10
只需要在上面的基础上加个1
保证值不重复
法1:暴力查找
每生成一个新的先在已生成的里面找,有重复的,就重新生成,没有,便可赋值。
缺点是时间复杂度不好。
/*
n是有效数字的个数(即已经生成了几个数)
value是要查找的值
若找到,便返回下标位置
*/
private static int FindValue(int[] br,int n,int value){
int pos=-1;
for(int i=0;i<n;i++){
pos=i;
break;
}
return pos;
}
private static void Init_Ar(int[] ar) {
Random random = new Random();
int tmp=0,j=0;
//方法1
for(int i=0;i<ar.length;i++){
//初始化为随机值 1...10
do{
tmp=random.nextInt(10)+1;
}while(FindValue(ar,i,tmp)!=-1);
ar[i]=tmp;
}
//方法2
while(j<ar.length){
int val=random.nextInt(10)+1;
if(FindValue(ar,j,tmp)!=-1){//若不重复
ar[j]=val;
++j;//不需要赋值,直接加一,就用++i吧
}
}
}
法2:查表
表的长度为数字种类数+1,(不是默认值0,就说明已经生成过该数)若没生成该数,将对应下标的数组值置为1
缺点:当数字种类多了,表长就过于大了
int[] table=new int[11];//产生数范围为1。。。10
while(j<ar.length){
int val=random.nextInt(10)+1;
if(table[val]==0){//若不重复
ar[j]=val;
table[val]=1;
++j;//不需要赋值,直接加一,就用++i吧
}
}
法3:HashNode(key,value)
- 若随机产生值的范围为1…100000,此时仍然只需要10个数。由于冲突可能性比较小,不便于使用上面的方式。
- 声明一个HashNode(key,value)类,其中key为关键码,即存放的数字,value是标志位,默认为0,表示该处没放值。
- 再定义一个 HashNode[] table,table的长度即为需要的随机数个数
- 此种方法用的不多,因为只能放数字,删除数字不好处理
class HashTable{
class HashNode{
int key;
int value;//标志位(默认为0,代表该处没放值)
public HashNode(int key, int value) {
this.key = key;
this.value = value;
}
}
HashNode[] table;
int maxsize;//个数(注意下标是0.。。maxsize-1)
public HashTable(int n) {
maxsize=n;//因为要生成指定数量个随机数
table=new HashNode[maxsize];
}
//仅生成hash值(即存放的位置)
public int Hash(int kx){
return kx%maxsize;//结果为0.。。maxsize-1
}
public int Inc(int i){//增量
return i;//线性探测
// return i*i;// 平方探测
}
// 解决Hash冲突
public int Hash_Inc(int kx,int i){
return (Hash(kx)+Inc(i))%maxsize;
}
//成功则为true,有重复值或满了则false
public boolean put(int kx){
boolean res=false;//res即result
for(int i=0;i<maxsize;i++){
/*
生成kx的hash地址,i用于处理冲突
若没进入任何一个if(即有哈希冲突 且 没发现有该值),就啥也不干到下一轮
*/
int pos=Hash_Inc(kx,i);
/*
没有哈希冲突,就 可以 放
注意:有哈希冲突不代表值相同,只是Hash地址一样,需要找下一个哈希位置
if和else if 最多只能进一个
*/
if(table[pos].value==0){
table[pos].key=kx;
table[pos].value=1;
res=true;
break;
}
/*
当上面不成立,才可能进到这里
即该位置有值 且 值为kx,就不试了,返回fasle
*/
else if(table[pos].key==kx){
break;
}
}
return res;
}
//有就返回下标
// public int get(int kx){
//
// }
}
HashTable ht=new HashTable(13);
while(j<ar.length) {
int val = random.nextInt(100000) + 1;
if (ht.put(val)) {//若不重复
ar[j] = val;
++j;
}
}
思考
-
链式处理冲突怎么写
-
链表过大怎么办?
- 可以将table扩容量,(新容量为素数可以分布的更均匀),然后重新插入那些值
- 也可以利用二次哈希,链接到第一个结点后面
- 可以将table扩容量,(新容量为素数可以分布的更均匀),然后重新插入那些值
法4:HashSet
- HashSet集合的特点:无序(存储顺序和取出顺序不一致)、唯一(不可重复)
- 由于HashSet集合存储元素是唯一的,所以当要求获取10个不能重复的随机数时,无需自主判断集合中是否包含该元素,只需将随机数添加到集合中即可
Random r = new Random();
HashSet<Integer> hs = new HashSet<Integer>(); //创建Integer类型的HashSet集合
while (hs.size() < 10) {
int num = r.nextInt(10) + 1;
hs.add(num);
}
利用HashSet判断数组有无重复值
//由于hashset实现了set接口,所以它不允许集合中有重复的值,
// 在调用add方法时,如果插入了重复值,不会插入,并且会返回false。
public static boolean cheakRepeat(int[] array){
HashSet<Integer> hashSet = new HashSet<Integer>();
boolean flag=true;
for (int i = 0; i < array.length; i++) {
if(hashSet.add(array[i])==false){
flag=false;
break;
}
}
return flag;
// if (hashSet.size() == array.length){
// return true;
// }else {
// return false;
// }
}
存字符串
若现在数组不是int型,存的是字符串。我们可以这样转化:将字母变为ASCII值 乘以每一位的权重