Leetcode刷题笔记|备战招聘|代码随想录(1)数组

一、理论基础

1、数组的元素是不能删的,只能覆盖。

2、array[2][3]只有有3*4=12个元素

3、C++二维数组的初始化

int a[3][4] = { 

 {0, 1, 2, 3},   /* 初始化索引号为 0 的行 */

 {4, 5, 6, 7},   /* 初始化索引号为 1 的行 */

 {8, 9, 10,11}   /* 初始化索引号为 2 的行 */

};

内部嵌套的括号是可选的,下面的初始化与上面是等同的: 

int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};

所以是按行分割

4、C++中二维数组在地址空间上是连续的,每两个地址差4,正好是个int的大小

5、java中二维数组不连续,可能为以下这样

二、二分查找

前提条件:数组有序,无重复元素,你必须设计并实现时间复杂度为O(log n) 的算法解决此问题

核心思想:假定target在【left,right】区间,用mid更新区间边界

错误提示:

1判断条件是数组元素nums【mid】,不是下标mid

2对于target超出数组边界的地方要约束,不然会超时

3mid要在循环内,不然无法更新

class Solution {

    public int search(int[] nums, int target) {

        intleft = 0, right = 0, mid = 0;

        intn = nums.length;

        right = n - 1;

        if (target < nums[0] || target > nums[n - 1])

       {

            return -1;

       }

        while (left

       {

            mid = (left +right) / 2;

            if (nums[mid] == target)

           {

                return mid;

           }

            else if(target

           {

               right = mid - 1;

           }

            else

           {

               left = mid + 1;

           }

       }

        return -1;

}

}

提升1 搜索插入位置

前提条件:

核心思想:每次区间内只剩2个元素的时候,left就是要插入的地方了

错误提示:

1超出数组边界的地方都写成了nums【left】

2mid= (left + right)/ 2,因为3/2=1.5=1

class Solution {

    public int searchInsert(int[] nums, int target) {

        intleft = 0;

        intposition = 0;

        intn = nums.length;

        intright = n -1;

        if (target < nums[left])

       {

            position = 0;

            return position;

       }

        if (target > nums[right])

       {

            position = right+ 1;

            return position;

       }

        while (left

       {

            int mid = (right + left) / 2 ;

            if (nums[mid] == target)

           {

                return mid;

           }

            else if (nums[mid] >target)

           {

               right = mid - 1;

           }

            else

           {

               left = mid + 1;

           }

       }

        return left;

   }    

}

提升2 在排序数组中查找元素的第一个和最后一个

前提条件:

核心思想:每次区间内只剩2个元素的时候,left就是要插入的地方了

错误提示:

1在数组内讨论时未注意约束数组越界问题

2返回类型必须遵从

3线性查找时间复杂度逼近O(logn)

4起始位置和结束位置分别开始二分查找

线性查找(超时):

class Solution {

    public int[] searchRange(int[] nums, int target) {

        //finalint  LENGTH = 100000;

        intleft = 0;

        intmid = 0;

        intpositionLeft= 0;

        intpositionRight= 0;

        intmoveFlag = 0;

        //int[][]res = new int[LENGTH][LENGTH];

        intn = nums.length;

        intright = n -1;

        //超出数组上下界

        if (target> nums[n - 1] || target < nums[0])//是或不是且

       {

            int[] res1 = {-1, -1};

            return res1;

       }

        else

       {

            //数组内的情况

            while (left

           {

                mid= (right + left) / 2;

                if (target == nums[mid])

               {

                   moveFlag = mid;

                   //看它下一个是否也是target

                   moveFlag++;

                   while (target == nums[moveFlag] &&moveFlag 1)//注意约束条件

                   {

                      positionRight = moveFlag;

                      moveFlag++;      

                   }

                   //看它上一个是否也是target

                   moveFlag = mid - 1;

                   while (target == nums[moveFlag] &&moveFlag >= 0)//注意约束条件

                   {

                      positionLeft = moveFlag;

                      moveFlag--;

                   }

               }

                else if (target >nums[mid])

               {

                   left = mid + 1;

               }

                else

               {

                   right = mid - 1;

               }

           }

            int[] res2 = {positionLeft,positionRight};

            return res2;

       }  

   }

}

二分查找(通过):

查找起始位置:首先,使用二分查找找到目标元素的起始位置。在二分查找中,当找到目标元素时,不要立即返回,而是继续向左(更小的索引方向)搜索,直到找到起始位置。

查找结束位置:接下来,使用二分查找找到目标元素的结束位置。在二分查找中,当找到目标元素时,不要立即返回,而是继续向右(更大的索引方向)搜索,直到找到结束位置。

class Solution {

    public int[] searchRange(int[] nums, int target) {

        intleft = 0;

        intn = nums.length;

        intright = n -1;

        intpositionLeft= getPositionLeft(nums, target);

        intpositionRight= getPositionRight(nums, target);    

        if (n == 0)

       {

            return new int[]{-1,-1};//数组的写法

       }  

        //超出数组上下界

        if (target> nums[right] || target < nums[0])//是或不是且

       {

            int[] res1 = {-1, -1};

            return res1;

       }

        //在数组内

        else

       {

             //在数组范围内却没有找到

            if (positionLeft == -2 ||positionRight == -2)//return后面不可以加句子

           {

                int[] res1 = {-1, -1};

                return res1;

           }

            else

           {

                int[] res2 = {positionLeft,positionRight};

                return res2;

           }

       }

}

    //左边界

    int getPositionLeft(int[] nums, int target){

        intleft = 0;

        int mid = 0; //mid使用之前要定义

        intn = nums.length;

        intright = n -1;

        intpositionLeft= -2;

        while (left

       {

            mid = (left +right) / 2;

            if (nums[mid] == target)

           {

               positionLeft = mid;

               right = mid - 1;

           }

            else if (nums[mid] >target)

           {

               right = mid - 1;

           }

            else

           {

               left = mid + 1;

           }

       }

        return positionLeft;

   }

    //右边界

    int getPositionRight(int[] nums, int target) {

        intleft = 0;

        intmid = 0;

        intn = nums.length;

        intright = n -1;

        intpositionRight= -2;

        while (left

       {

            mid = (left +right) / 2;

            if (nums[mid] == target)

           {

               positionRight = mid;

               left = mid + 1;

           }

            else if (nums[mid]

           {

               left = mid + 1;

           }

            else

           {

               right = mid - 1;

           }

       }

        return positionRight;

   }

}

提升3 x的平方根

前提条件:

核心思想:二分查找存在的意义就是简化顺序查找

错误提示:

1在 square < x 的情况下,更新 res 为 mid,以便在没有找到完全匹配的情况下,返回最接近的整数平方根。

2mid溢出了,是最大的问题。最后用long解决,但是返回值要是int。 

class Solution {

       publicint mySqrt(int x) {

        //存在的意义就是简化顺序查找

        longleft = 0;

        longright = x;

        long mid = 0;//int是32位

        intres = 0;

        long flag = 0;//两个int相乘

        //mid=right/2;

        while (left

       {

            mid = left +(right - left) / 2;

           flag = mid * mid;

            if (flag == x)

           {

                res= (int)mid;

                //System.out.println(res);

                return res;

           }

            else if (flag > x)//不合格的状态

           {

               right = mid - 1;

           }

            else//这个情况也要返回因为如果找不到恰好的,就找接近的。

           {

                res= (int)mid;

               left = mid + 1;

           }

       }

        return res;

   }

}

提升4 有效的完全平方数

前提条件:

比上一题简单一点,因为只有平方恰好=target,才是唯一的可行情况,没有近似的这个想法。

错误提示:

1squre忘记放进循环了。

2比较条件的时候需要把int强制类型转化成long,不然会无脑判fasle的。

class Solution {
    public boolean isPerfectSquare(int num) {
        int left = 0;
        int right = num;
        long mid = 0;
        while (left <= right)
        {
            mid = left + (right - left) / 2;
            long square = mid * mid;
            if (square == (long)num)
            {
                return true;
            }
            else if (square > (long)num)
            {
                right = (int)mid - 1;
            }
            else
            {
                left = (int)mid + 1;
            }
        }
        return false;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_53077632/article/details/134844235