锻练编程思维——每日一题:《剑指offer》数组中重复的数字

题目描述

题目描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
题目给的代码:

class Solution {
public:
    // Parameters:
    //        numbers:     an array of integers
    //        length:      the length of array numbers
    //        duplication: (Output) the duplicated number in the array number
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    bool duplicate(int numbers[], int length, int* duplication) {
        
    }
};

很经典的一道题,但是想出一个很好的题解却很难。(记忆吧还是,我目前的水平很难理解这样的算法)

题目分析

  • 鉴于形参有长度和数组,所以先做一个异常处理,如果长度小于0或者数组为空,就返回false,连查重都不用了。
  • 首先我肯定是要遍历这个数组,要不然你怎么知道有没有重复的数字?而在步进到每个数组元素的时候我想着是把这个数字记录下来。
  • 不过这样我需要多开一个数组,会不会空间复杂度就大了呢?
  • 所以,就有了下面这个算法,利用“控制变量法”,暂时固定下标(索引index)值,然后查看下标(索引index)对应的元素值是否等于下标
    • 等于的话无可奉告,下标++,再查看下标对应的元素值是否==下标
    • 不等于,就设一个临时变量值并赋值其下标对应的元素值,然后比较临时变量值和临时变量值做下标对应的元素值是否相等
      • 如果临时变量值==临时变量值做下标对应的元素值证明找到了数组中任意一个重复的数字,就让duplication指针(或称数组名)的duplication[0]存放临时变量值(找到的数组中任意一个重复的数字),然后返回true
      • 如果临时变量值不等于临时变量值做下标对应的元素值,就直接交换下标对应的元素值临时变量值做下标对应的元素值

本着这样一个思想。就可以写出代码:

题解代码

class Solution {
public:
    // Parameters:
    //        numbers:     an array of integers
    //        length:      the length of array numbers
    //        duplication: (Output) the duplicated number in the array number
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
//有重复的数字返回true,无重复的数字或其他情况返回false
    bool duplicate(int numbers[], int length, int* duplication) {
        if(length<=0||numbers==NULL)//异常处理,注意这个NULL必须大写!!!记住!
        {
            return false;
        }
        int index=0;//下标值,初始化为0
        while(index<length)//下标值做暂时固定作用并适时自增步进直到数组倒数第一个元素
        //这里不能写index<=length,因为数组从0开始,如果index==length,numbers[length]不就越界了?
        
        {
            if(numbers[index]==index)//下标(索引index)对应的元素值是否等于下标
            {
                index++;
            }
            else
            {
                int tmp=numbers[index];//设置一个临时变量值并赋值其下标对应的元素值
                if(numbers[tmp]==tmp)
                //比较临时变量值和临时变量值做下标对应的元素值是否相等
                //实质上numbers[tmp]和numbers[index]去比较
                {
                	//临时变量值和临时变量值做下标对应的元素值相等
                    duplication[0]=tmp;
                    return true;
                }
                else//临时变量值和临时变量值做下标对应的元素值不相等
                {
                	//交换==下标对应的元素值==和==临时变量值做下标对应的元素值
                    numbers[index]=numbers[tmp];
                    numbers[tmp]=tmp;
                }
            }
        }
        return false;//注意这里,如果数组都遍历完了没找到重复的数字,就返回false!!!!
    }
};

学习一些思想和注意的地方!切记!

还是有很多值得学习的地方得,比如
①null一定写成大写,就是NULL,小写null会让编译器报错
②拿到题要观察形参表的形参存不存在接收无效实参的情况,如果存在可能接收瞎传进来的(无效的)实参的情况,必须做异常处理!
③思考循环成立条件时,如果循环体内有数组或数组元素/下标相关的代码要思考数组越界这个问题!不能顾这个不顾那个!

这个算法思想不错,咱给记下来吧!!!!

你可能感兴趣的:(数据结构,算法)