第九周LeetCode算法题两道

本文解析了LeetCode上的两道中等难度题目:49. Group Anagrams 和 33. Search in Rotated Sorted Array。首先介绍了如何通过排序来解决字母异位词分组的问题,并给出AC代码。接着探讨了在旋转排序数组中使用二分查找法进行搜索的有效策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一道

题目名称:49. Group Anagrams

题目难度:Medium

题目描述:Given an array of strings, group anagrams together.

For example, given: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”],
Return:

[
  ["ate", "eat","tea"],
  ["nat","tan"],
  ["bat"]
]

Note: All inputs will be in lower-case.

题目分析:
题目要求我们将输入的字符串分类。分类的依据是含有相同的字母且相同字母对应的数量相等。

思路很简单直接。既然在同一组的每个字符串之间不同的只是字母的顺序,那么将他们的字母都排序后,同一组的字符串排序的结果一定相等。这样我们就将它们分类开来了。

排序用的是一个char类型的multiset容器。

最终AC的代码是:

class Solution {
public:
    vector<vector<string> > groupAnagrams(vector<string>& strs) {
        vector<vector<string> > result;
        vector<string> sort;
        for (int i = 0; i < strs.size(); ++i) {
            multiset<char> temp_set;
            string tStr = "";
            for (int j = 0; j < strs[i].size();++j) {
                temp_set.insert(strs[i][j]);
            }
            for (set<char>::iterator it = temp_set.begin(); it != temp_set.end(); ++it) {
                tStr += *it;
            }
            sort.push_back(tStr);
        }
        bool visit[strs.size()];
        memset(visit, 0, sizeof(visit));
        for (int i = 0; i < strs.size(); ++i) {
            vector<string> temp;
            if (visit[i] == 0) {
                temp.push_back(strs[i]);
                visit[i] = 1;
                for (int j = i + 1; j < strs.size(); ++j) {
                    if (sort[j] == sort[i]) {
                        temp.push_back(strs[j]);
                        visit[j] = 1;
                    }
                }
            }
            if (temp.size() != 0)
                result.push_back(temp);
        }
        return result;
    }
};

第二道

题目名称:33. Search in Rotated Sorted Array

题目难度:Medium

题目描述:Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

题目分析:
本题乍一看好像特别简单。就是在一个数组之内找一个指定的值。这样好像直接暴力搜索遍历一遍数组就好了。但是这样的话这道题为什么不归类到“easy“难度呢?那就说明了这道题有可能对运行时间有限制,O(n)的时间肯定是过不了了。但是抱着试一试的心态,我跑了一次O(n)级别的搜索,居然直接过了!但是感觉这道题肯定不是这么简单。
于是到题目的讨论区看了看。最高记录是用二分查找法来做的。它的做法是:先用二分查找找出数组最小的一个数,这个数所在的位置也就是数组旋转的支点。这样子直接将target目标数可能在的范围直接限制在由这个支点分开的两个不同范围其中一个。然后再从这个新范围中做经典的二分查找搜索(此时的新范围已经排好序了)

最后AC的我的算法是:(暴力搜索)

class Solution {
public:
    int search(vector<int>& nums, int target) {
        bool flag = false;
        for (int i = 0; i < nums.size(); ++i) {
            if (nums[i] == target) {
                flag = true;
                return i;
            }
        }    
        if (flag == false)
            return -1;
    }
};

评论区中使用两次二分搜索的代码是:

class Solution {
public:
    int search(int A[], int n, int target) {
        int lo=0,hi=n-1;
        // find the index of the smallest value using binary search.
        // Loop will terminate since mid < hi, and lo or hi will shrink by at least 1.
        // Proof by contradiction that mid < hi: if mid==hi, then lo==hi and loop would have been terminated.
        while(lo<hi){
            int mid=(lo+hi)/2;
            if(A[mid]>A[hi]) lo=mid+1;
            else hi=mid;
        }
        // lo==hi is the index of the smallest value and also the number of places rotated.
        int rot=lo;
        lo=0;hi=n-1;
        // The usual binary search and accounting for rotation.
        while(lo<=hi){
            int mid=(lo+hi)/2;
            int realmid=(mid+rot)%n;
            if(A[realmid]==target)return realmid;
            if(A[realmid]<target)lo=mid+1;
            else hi=mid-1;
        }
        return -1;
    }
};

有一点比较有意思的是,我参考了评论区二分搜索的代码重新写了一次之后,发现运行时间还不如我原来的O(n)算法。个人觉得一个可以解释的原因是,当数据量很大的时候,logN算法肯定是优于N算法的,但数据较小的时候,前者时间比后者长属于正常现象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值