Day_01

Day 01

数组

数组是存放在连续内存空间上的相同类型的数据的集合,数组可以通过下标索引的方式获取到下标下对应的数据。

image-20230628103433084

**数组的元素是不能删的,只能覆盖。**地址为16进制,二维数组地址是连续一条线的。

像Java是没有指针的,同时也不对程序员暴露其元素的地址,寻址操作完全交给虚拟机,所以看不到每个元素的地址情况。

public static void test_arr() {
    int[][] arr = {{1, 2, 3}, {3, 4, 5}, {6, 7, 8}, {9,9,9}};
    System.out.println(arr[0]);
    System.out.println(arr[1]);
    System.out.println(arr[2]);
    System.out.println(arr[3]);
}
[I@7852e922
[I@4e25154f
[I@70dea4e
[I@5c647e05

这里的数值也是16进制,这不是真正的地址,而是经过处理过后的数值了,我们也可以看出,二维数组的每一行头结点的地址是没有规则的,更谈不上连续。

704. 二分查找

前提是数组为有序数组,同时题目还强调数组中无重复元素,因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的,这些都是使用二分法的前提条件。

写二分法,区间的定义一般为两种,左闭右闭即[left, right],或者左闭右开即[left, right)。

  • [left, right]

定义target在[left, right]区间

if (nums[middle] > target), right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1

python
class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        left = 0
        right = len(nums)-1

        while left <= right:
            middle = left + (right - left) // 2
            if nums[middle] > target:
                right = middle-1
            elif nums[middle] < target:
                left = middle + 1
            else:
                return middle
        return -1
  • [left, right)

定义 target 是在一个在左闭右开的区间里

  • while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的

  • 因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle

注:左闭右开区间内,查找的范围必不包括right,所以这时候的赋值right更新为middle

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        left = 0
        right = len(nums)

        while left < right:
            middle = left + (right - left) // 2
            if nums[middle] > target:
                right = middle
            elif nums[middle] < target:
                left = middle + 1
            else:
                return middle
        return -1

总结:当左闭右闭时,例如我们可以查找【2,2】区间,当左闭右开时,我们只能查找【2,3】区间,所以此时对于left的定义有区别,前者可以减一,后者不可。所以对于前者,middle赋值的时候可以-1.

Java

class Solution {
    public int search(int[] nums, int target) {
        if (target nums[nums.length - 1]) {
            return -1;
        }
        int left = 0, right = nums.length - 1;
        while (left<=right) {
            int middle = left + ((right - left)>>1); //右移一位相当于除2,右移n位相当于除以2的n次方。
            if (nums[middle] < target)
                left = middle + 1;
            else if (nums[middle] > target)
                right = middle - 1;
            else if (nums[middle] == target)
                return middle;
        }
        return -1;

    }
}
class Solution {
    public int search(int[] nums, int target) {
        if (target nums[nums.length - 1]) {
            return -1;
        }
        int left = 0, right = nums.length;
        while (left>1); //右移一位相当于除2,右移n位相当于除以2的n次方。
            if (nums[middle] < target)
                left = middle + 1;
            else if (nums[middle] > target)
                right = middle ;
            else if (nums[middle] == target)
                return middle;
        }
        return -1;

    }
}

27. 移除元素

暴力解法

这个题目暴力的解法就是两层for循环,一个for循环遍历数组元素 ,第二个for循环更新数组。

python
class Solution(object):
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        i = 0
        a = len(nums)
        while i < a:
            if nums[i] == val:
                for j in range(i+1,a):
                    nums[j-1] = nums[j]
                i -= 1
                a -= 1
            i += 1

        return a 
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)

双指针法

双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

  • 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
  • 慢指针:指向更新 新数组下标的位置
class Solution(object):
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        a = len(nums)
        fast = 0
        slow = 0
        while fast < a:
            if nums[fast] != val:
                nums[slow] = nums[fast] 
                slow += 1
            fast += 1
        return slow

注:双指针法,一个快指针判断,慢指针接收。注意思想,判断不一定是正判断,逆判断有时候效果更好。

Java

class Solution {
    public int removeElement(int[] nums, int val) {
        int slow = 0;
        for (int fast = 0; fast < nums.length; fast++){
            if (nums[fast] != val){
                nums[slow] = nums[fast];
                slow++;
            }
        }
        return slow;

    }
}

你可能感兴趣的:(算法)