下面所有代码采用 java 编写
1.针对给定的⼀维数组,⽐如[1, 1, 34, 9, 45, 8, 3, 21, 6, 1, 8, 3, 7, 6, 22, 88, 34, 21];请使⽤⼀次 for循环,找出所有的重复数字以及重复数字的次数;
思路
对于给定的数组,我们对每一个元素和后面的每一个元素都进行比较,如果相等计数器加一,这样就能得出重复的元素和个数了。
但是这样有个问题,后面重复的元素再跟后面的元素比较,这样就会重复打印,而且第二次打印就会比上一次打印的少计算一个,我们需要把这种情况剔除掉。步骤
1.遍历整个数组,依次的拿到每一个的数值
2.在循环内部,对于拿到的元素需要和之前的进行比较,如果相同就得跳过这次比较,因为这个已经打印过了。
3.对于没比较的,可以循环的和后面的每一次进行比较
4.对于计数器大于1的,说明重复了
代码实现
@Test
public void getRepeatNum(){
List<Integer> list = Arrays.asList(1, 1, 34, 9, 45, 8, 3, 21, 6, 1, 8, 3, 7, 6, 22, 88, 34, 21);
//1.遍历整个数组,依次的拿到每一个的数值
for(int i = 0;i < list.size();i++){
//2.先判断这个元素之前是不是已经计算过了
boolean flag = false;
for(int k=0;k<i;k++){
if(list.get(k) == list.get(i)){
flag = true;
//只要发现是计算过,直接跳出循环,节省资源
break;
}
}
//计算过了就直接下一步
if(flag){
continue;
}
//3.之前没有计算过 重新计算
int count = 1; //计数器初始值是1,因为每个元素至少出现1次
for(int j= i+1;j < list.size();j++){
if(list.get(i) == list.get(j)){
count++;
}
}
//4.计算大于1,就打印出来
if(count>1){
System.out.println("重复元素" + list.get(i) + "出现了" + count + "次");
}
}
}
这样整个方法就出来了,思路很清晰,也去除了重复比较的问题,但是题目要求一个for循环。
思路
将第二步和第三步的内部for循环改写成递归调用
代码实现
@Test
public void getRepeatNum2(){
List<Integer> list = Arrays.asList(1, 1, 34, 9, 45, 8, 3, 21, 6, 1, 8, 3, 7, 6, 22, 88, 34, 21);
//1.遍历整个数组,依次的拿到每一个的数值
for(int i = 0;i < list.size() - 1;i++){
if(i != 0){
//2.先判断这个元素之前是不是已经计算过了
boolean bool = compareBefore(list, i, 0);
//计算过了就直接下一步
if(bool){
continue;
}
}
//3.之前没有计算过 重新计算
int count = 1; //计数器初始值是1,因为每个元素至少出现1次
count = repeaSearch(list, i, i + 1, count);
//4.计算大于1,就打印出来
if(count>1){
System.out.println("重复元素" + list.get(i) + "出现了" + count + "次");
}
}
}
public static boolean compareBefore(List<Integer> list,int index,int first){
if(list.get(index) == list.get(first)){
return true;
}else if(first < index -1 ){
return compareBefore(list,index,first+1);
}else {
return false;
}
}
public static int repeaSearch(List<Integer> list,int index, int end,int count){
if(list.get(index) == list.get(end)){
count++;
}
if(end < list.size() -1 ){
return repeaSearch(list,index,end+1,count);
}else {
return count;
}
}
2.给定指定数组,⽐如【1, 2, 3, 4, 5, 6, 7, 8, 9, 10】,在数组中查找⼀个元素的下标,要求:使 ⽤递归⽅式、⼆分查找算法、不得使⽤所使⽤语⾔已有的函数;
这里对于递归调用和二分法查找,我们有个前提是这个数组是不重复的,而且是已经排序完成的数组
这样我们对于已经排序完成的数组,进行查找才能精确的查找到下标的位置思路
1.先进性排序 排序后是我们需要查找下标的数组 打印出来
2.递归的方法代替for循环,二分法查找
代码实现
@Test
public void getRepeatSubscript(){
List<Integer> list = Arrays.asList(1,5,7,8,19,3,58,65,27,2); //查找下标,我们限定数组不重复
//1.先进行排序 冒泡
for(int i = 0;i < list.size();i++){
for(int j= i+1;j < list.size();j++){
if(list.get(i) > list.get(j)){
Collections.swap(list,i,j); //交换元素位置
}
}
}
System.out.println("查找的目标数组:" + list); //这个数组才是我们最终查找的下标
//2.进性二分法查找 递归
int i = binarySearch(list, 19, 0, list.size());//查找19
System.out.println("下标位置为" + i);
}
public static int binarySearch(List<Integer> list,int num,int min,int max){
if(max < min){
return -1; //查不到返回-1
}
int mid = (max + min)/2;
if(list.get(mid) == num){
return mid;
}else if(list.get(mid) > num){
return binarySearch(list,num,min,mid-1);
}else {
return binarySearch(list,num,mid+1,max);
}
}
3.编程题:有⼀堆糖果,其数量为n,现将糖果分成不同数量的堆数(每堆数量均为整数,最少为 1),请算出糖果堆对应数量的最⼤乘积是多少,并给出对应的分配⽅案; 举例:糖果数量为8,可以得到的乘积最⼤为18,对应的分配⽅案为【2,3,3】;
这里我们思考了一下如何让乘积最大
1.1要首先排除掉
2.分解的堆数尽量多
3.做到每个数都想接近我们把这个数 2 * 3 的方式分解 得到的* 最大 尽量多的3
但是不能有1 有1 就得把1 加在2 上第一种情况,刚好是三的倍数,直接相乘
第二种情况,余数是1 这种坚决要不得 少一个3 变成2* 2
第三种情况 余数为2 那就直接*2就行
代码实现
@Test
public void greedyAlgorithm(){
int num = 15;
//1 2 3 4 不在算法计算之内
switch (num){
case 1:
System.out.println("最大的乘积1");
case 2:
System.out.println("最大的乘积1");
case 3:
System.out.println("最大的乘积2");
case 4:
System.out.println("最大的乘积4");
}
//我们从5开始考虑,尽量多的3
int number = num/3; //算出几个3
int remainder = num - 3*number;
int product = 1;
if(remainder == 0){
//第一种情况,刚好是三的倍数,直接相乘
for (int i = 0;i<number;i++ ){
product = product *3;
}
}else if(remainder == 1){
//第二种情况,余数是1 这种坚决要不得 少一个3 变成2* 2
for (int i = 0;i<number-1;i++ ){
product = product *3;
}
product = product *2*2;
}else {
//第三种情况 余数为2 那就直接*2就行
for (int i = 0;i<number;i++ ){
product = product *3;
}
product = product *2;
}
System.out.println(product);
}