刷题记录5---旋转图像+两数之和+字母异位词分组+最长连续序列+跳跃游戏

前言

所有题目均来自力扣题库中的hot 100,之所以要记录在这里,只是方便后续复习

48.旋转图像

题目:
给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
示例 1:
旋转图像

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]
示例 2:
输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]
解题思路:
【找规律】先上下翻转,再对角线翻转,即可达到顺时针旋转90度效果;翻转即交换两个位置的值
代码(python):

class Solution(object):
    def rotate(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: None Do not return anything, modify matrix in-place instead.
        """
        n = len(matrix)
        # 上下翻转 
        for i in range(0, n / 2):
            for j in range(0, n):
                # 即i j 位置 和 n-i-1 j位置交换值
                matrix[i][j], matrix[n - i -1][j] =  matrix[n - i -1][j], matrix[i][j]
        # 对角线翻转 对角线位置是从左上到右下
        for i in range(0, n):
            for j in range(0, i):
                # 即i j 位置和 j i位置交换值
                matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]

        return matrix

代码(java):

class Solution {
    public void rotate(int[][] matrix) {
        int n = matrix.length;
        int temp = 0;

        for(int i = 0; i < n/2; i++){
            for(int j = 0; j < n; j++){
                temp = matrix[i][j];
                matrix[i][j] = matrix[n - i - 1][j];
                matrix[n - i - 1][j] = temp;
            }
        }
        
        for(int i = 0; i < n; i++){
            for(int j = i; j < n; j++){
                temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i]= temp;
            }
        }

    }
}

知识点:

  • python中交换两个值可以用 val1, val2 = val2, val1

原题链接:旋转图像

1.两数之和

题目:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
解题思路:
【Hash表】遍历给定数组,假设选中每个位置为第一个数后,再遍历数组寻找第二个数的位置即可,但是这种暴力方法的时间复杂度为N方。我们可以优化寻找第二个数的过程,借用hash表结构,也就是python中的dict或java中的HashMap。因为hash结构寻找某一个数的时间复杂度是1,这样总体的时间复杂度即为N。优化后的过程:定义dict,键为nums的值,值为nums的索引;遍历给定数组,对于每个位置值num判断一下target - num是否在dict的键中,如果在则返回该位置的索引和target - num在dict中的值即可 。如果不在则将该位置的值和索引放入dict即可
代码(python):

class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        hash_nums = dict()
        for i, num in enumerate(nums):
            if hash_nums.has_key(target - num):
                return [i, hash_nums[target - num]]
            hash_nums[num] = i 

代码(java):

class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer, Integer> table = new HashMap<Integer, Integer>();
        for(int i=0;i<nums.length;i++){
            if(table.containsKey(target-nums[i])){
                return new int[]{table.get(target - nums[i]), i};
            }
            table.put(nums[i], i);
        }
        return new int[0];
    }
}

知识点:

  • 要在数组中快速寻找某个数,优先考虑hash结构
  • python遍历字典的写法,可以用枚举:for i, num in enumerate(dict)
  • 对于字典是否包含某个键,python有has_key()方法,java有containsKey()方法

原题连接:两数之和

49.字母异位词分组

题目:
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。
示例 1:
输入: strs = [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”]
输出: [[“bat”],[“nat”,“tan”],[“ate”,“eat”,“tea”]]
示例 2:
输入: strs = [“”]
输出: [[“”]]
示例 3:
输入: strs = [“a”]
输出: [[“a”]]
解题思路:
【Hash表】将字符串分组就要找到其共同点:由相同的字符串组成,只不过顺序不同,那排序后的字符串就是相同的,所以我们可以用排序后的字符串的当作键,字符串组成的列表当作值,定义一个Hash结构,并依次将字符串添加进行就达到了分组效果
代码(python):

class Solution(object):
    def groupAnagrams(self, strs):
        """
        :type strs: List[str]
        :rtype: List[List[str]]
        """
        results = collections.defaultdict(list)

        for s in strs:
            key = "".join(sorted(s))
            results[key].append(s)
        
        return list(results.values())

代码(java):

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        // 定义hashmap结构存储结果
        HashMap<String, ArrayList<String>> result = new HashMap<>();
        // 对于每一个字符串
        for (int i = 0; i < strs.length; i ++){
            // 将字符串转为 char数组,用系统方法进行排序后,重新转为字符串
            char[] array = strs[i].toCharArray();
            Arrays.sort(array);
            String key = new String(array);
            // 根据排序后的字符串当作hashmap 的key,将该字符串添加到hashmap中
            ArrayList<String> list = result.getOrDefault(key, new ArrayList<String>());
            list.add(strs[i]);
            result.put(key, list);
        }
        // 最后将hashmap转化链表返回
        return new ArrayList<>(result.values());
    }
}

知识点:

  • python中若想定义一个字典,且字典里默认的值都是默认列表,可以用collections.defaultdict(list)写法
  • python中对字符串(可迭代对象)排序可以用sorted(str),其返回值是新的列表;而list.sort()方法是对列表原地排序,无返回值
  • python中将列表拼接成字符串可以用"".join(list)写法
  • java中对字符串排序可以先用str.toCharArray()方法将字符串转为char数组,然后用Arrays.sort(array)对数组进行原地排序,最后用new String(array)字符串的构造方法重新转成新字符串
  • java中hashmap转为ArrayList,可以用 new ArrayList(hashmap.values());其中hashmap.values()返回map中所有value组成的集合

原题链接:字母异位词分组

128.最长连续序列

题目:
给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) 的算法解决此问题。
示例 1:
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
示例 2:
输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9
解题思路:
【Hash表】正常思路是遍历每个值,然后依次寻找该值的后续值 + 1 +2 +3 直到 +n是否在数组中,最后取最大值即可,但是这个时间复杂度较高,是否可优化呢;第一个点,是不是每个值都需要取寻找后续值呢?不是,只有当该值 - 1不在数组中时才需寻找,因为若该值 - 1 在数组中,在遍历到该值 - 1的时候就已经包含了该值的情况,无需重复操作;第二个点是,如果快速判断出某个值在不在数组中,所以联想到用hash结构,将数组转为为hash表即可
代码(python):

class Solution(object):
    def longestConsecutive(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """

        if nums is None or len(nums) == 0:
            return 0
        
        values = set(nums)
        max_len = 0

        for val in values:
            if val - 1 not in values:
                cur_len = 1
                num = val + 1
                while num in values:
                    cur_len += 1
                    num += 1
                max_len = max(max_len, cur_len)

        return max_len 

代码(java):

class Solution {
    public int longestConsecutive(int[] nums) {
        // 定义hash表,将数组中的值依次添加到hash表
        HashSet<Integer> set = new HashSet<>();
        for(int val: nums){
            set.add(val);
        }
        //定义结果值
        int result = 0;
        //遍历hash表
        for(int val: set){
            // 如果当前值 - 1 不在hash表中,再去查看以当前值为开头的序列能有多长
            if(set.contains(val - 1) == false){
                // 定义当前长度
                int cur = 0;
                //如果当前值在hash表中,长度+1,并且当前值+1
                while(set.contains(val)){
                    cur ++;
                    val = val + 1;
                }
                //取当前长度和结果值的较大值赋给结果值
                result = Math.max(result, cur);
            }
        }
        return result;
    }
}

知识点:

  • java中HashSet为Hash表结构,可以去重也可以O1寻找某值,add(val)为添加方法,contains(val)为判断是否包含某个元素,没有get方法
  • python中可以用set(list)将列表转为set集合

原题链接:最长连续序列

55.跳跃游戏

题目:
给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个下标。
示例 1:
输入:nums = [2,3,1,1,4]
输出:true
解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。
示例 2:
输入:nums = [3,2,1,0,4]
输出:false
解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。
解题思路:
【贪心算法】我们可以计算每个位置能跳的最远距离,如果最远距离大于等于了末尾位置,那就可以到达;所以我们要遍历整个数组,根据每个值能跳的距离和当前位置去更新最远距离;需要注意的是在获取当前位置的最远距离之前要判断一下当前位置是否在当前最远距离内,若不在,则说明到达当前位置,便不能选用当前位置
代码(python):

class Solution(object):
    def canJump(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        # 定义能跳的最远距离
        max_dis = 0
        n = len(nums)
        # 对于每个位置
        for i in range(0, n):
            # 如果当前位置在能跳的最远距离内  很重要的判断
            if i <= max_dis:
                # 根据当前位置能跳的值更新最远的距离
                max_dis = max(i + nums[i], max_dis)
                # 如果最远距离包含了数组结尾 直接返回True
                if max_dis >= len(nums) - 1:
                    return True
        # 若遍历整个数组最远距离都没达到末尾,则返回False
        return False

代码(java):

public class Solution {
    public boolean canJump(int[] nums) {
        int n = nums.length;
        int rightmost = 0;
        for (int i = 0; i < n; ++i) {
            if (i <= rightmost) {
                rightmost = Math.max(rightmost, i + nums[i]);
                if (rightmost >= n - 1) {
                    return true;
                }
            }
        }
        return false;
    }
}

知识点:

原题连接:跳跃游戏

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值