2021-11-29 力扣169,287,162

169. 多数元素

方法一:利用哈希表来找出现次数大于n/2的元素,没有啥难度

class Solution {
    public int majorityElement(int[] nums) {
        //根据题意一定要分析出多数元素一个数组中只能有一个数
        int n = nums.length;
        int num = 0;
        Map<Integer,Integer> map = new HashMap<>();
        for(int x: nums){
            map.put(x,map.getOrDefault(x,0)+1);
            if(map.get(x) > n/2){
               num = x;
           }
        }
        return num;
    }
}

方法二:新思想:

摩尔投票法思路
候选人(cand_num)初始化为nums[0],票数count初始化为1。
当遇到与cand_num相同的数,则票数count = count + 1,否则票数count = count - 1。
当票数count为0时,更换候选人,并将票数count重置为1。
遍历完数组后,cand_num即为最终答案。

为何这行得通呢?
投票法是遇到相同的则票数 + 1,遇到不同的则票数 - 1。
且“多数元素”的个数> ⌊ n/2 ⌋,其余元素的个数总和<= ⌊ n/2 ⌋。
因此“多数元素”的个数 - 其余元素的个数总和 的结果 肯定 >= 1。
这就相当于每个“多数元素”和其他元素 两两相互抵消,抵消到最后肯定还剩余至少1个“多数元素”。

class Solution {
    public int majorityElement(int[] nums) {
        int x = nums[0];
        int count = 1;
        for(int i=1;i<nums.length;i++){
            if(x == nums[i]){
                count++;
            }else{
                count--;
            }
            if(count == 0){ 
            x = nums[i];
            //卡在这一步,换数后忘了再把count也重新赋值为1
            count = 1;
            }
        }
        return x;
    }
}
287. 寻找重复数

方法一:无脑暴力法

class Solution {
    public int findDuplicate(int[] nums) {
        int num = nums[0];
        Arrays.sort(nums);
        for(int i=0;i<nums.length-1;i++){
            if(nums[i] == nums[i+1]){
                num = nums[i];
            }
        }
        return num;
    }
}

方法二:函数思想

class Solution {
    public int findDuplicate(int[] nums) {
    //将题目给的特殊的数组当作一个链表来看,数组的下标就是指向元素的指针,把
    //数组的元素也看作指针。如 0 是指针,指向 nums[0],而 nums[0] 也是针, 
    //指向 nums[nums[0]].
    int fast = 0;
    int slow = 0;
    int c = 0;
        while(true){
         //   nums[fast] = nums[nums[fast]];
         fast = nums[nums[fast]];//快指针,相当于 .next.next
         slow = nums[slow]; //慢指针,相当于.next
            if(fast == slow){
                break;
            }

        }
        //难点:找到重合后清零然后同步走
        while(nums[c] != nums[slow]){
            c = nums[c];
            slow = nums[slow];
        }
        return nums[slow];
    }
}
162. 寻找峰值
class Solution {
    public int findPeakElement(int[] nums) {
        int left = 0;
        int right = nums.length-1;
        while(left < right){
            int mid = left + (right - left)/2;
            if(nums[mid] > nums[mid+1]){
                //right = mid-1;
                //right可能就是峰顶
                right = mid;
            }else{
                left = mid+1;
            }
        }
        return left; 
    }
}

思路:
爬山,如果你往下坡方向走,也许可能遇到新的山峰,但是也许是一个一直下降的坡,最后到边界。但是如果你往上坡方向走,就算最后一直上的边界,由于最边界是负无穷,所以就一定能找到山峰,总的一句话,往递增的方向上,二分,一定能找到,往递减的方向只是可能找到,也许没有。

<think>好的,我现在需要解决如何检查一个字符串中每个字符出现的次数是否相同的问题。根据用户提供的引用信息,特别是引用[4],里面提到了使用数组来统计字符出现次数的方法。让我仔细想想应该怎么做。 首先,用户的问题是要检查字符串中所有字符的出现次数是否相同。例如,字符串“aabbcc”中每个字符出现两次,而“aaabbb”中a出现三次,b出现三次,这种情况也符合要求。但像“aabba”这种,a出现三次,b两次,就不符合。 根据引用[4]中的思路,我们可以使用一个大小为26的数组来记录每个字符出现的次数。这里假设字符串只包含小写字母,如果是其他字符可能需要更大的数组或者哈希表。不过题目如果是力扣的话,可能只考虑小写字母,所以数组大小26足够。 步骤应该是这样的: 1. 统计每个字符的出现次数。遍历字符串,对每个字符对应的数组位置进行计数。例如,字符‘a’对应索引0,‘b’对应1,依此类推。可以用字符减去‘a’的ASCII码来得到索引。 2. 然后需要检查这些次数是否全部相同。这时候需要处理数组中的非零元素,因为它们代表实际出现的字符的次数。 可能出现的情况是,数组中有些位置是0,说明对应的字符没有出现过。所以需要过滤掉这些0,然后检查剩下的所有值是否相同。 比如,假设数组统计后的次数是[3,3,0,0,...],那么有效次数是3和3,都相同。但如果次数是[2,3,1,0,...],则不相同。 所以具体步骤可能是: - 遍历数组,收集所有非零的计数。 - 检查这些计数是否全部等于第一个非零的计数。或者更准确地说,检查所有非零计数是否相同。 但这里有个问题,比如字符串“aaa”,数组中只有a的位置是3,其他都是0。这时候所有的非零计数都是3,符合条件。 还有一种情况是,如果字符串中有多个不同字符,但它们的次数都相同,比如“aabb”次数是2和2,符合条件。 所以,实现的关键点在于: - 统计次数。 - 收集所有非零次数。 - 检查这些次数是否一致。 但是,可能存在特殊情况,例如所有字符出现的次数都是0?这应该是不可能的,因为字符串至少有一个字符。或者如果字符串为空的话,可能需要处理边界情况,但题目可能假设字符串非空。 然后,根据引用[4]中的代码,他们统计了两个字符串的次数,并比较是否每个字符的次数相减后都为0。但这里的问题不同,我们需要同一个字符串中的所有字符次数相同。 比如,解决方案应该首先统计每个字符出现的次数,然后过滤掉零,然后检查剩下的所有值是否相同。 具体实现步骤: 1. 初始化一个长度为26的数组,初始值为0。 2. 遍历字符串中的每个字符,将对应的数组位置加1。 3. 遍历数组,收集所有非零的值。 4. 检查这些值是否全部相等。 例如: 对于字符串“abba”,统计后的数组是[2,2,0,...],非零值为2和2,相同,返回true。 对于字符串“aaabbb”,统计后数组是[3,3,0,...],返回true。 对于字符串“aab”,统计后数组是[2,1,0,...],非零值为2和1,不同,返回false。 可能的实现代码: 使用Java的话,可以类似引用[4]中的方法: public boolean checkFrequency(String s) { int[] count = new int[26]; for (char c : s.toCharArray()) { count[c - 'a']++; } int expected = 0; for (int num : count) { if (num != 0) { if (expected == 0) { expected = num; } else if (num != expected) { return false; } } } return true; } 或者,可能需要处理所有非零值是否相同。例如,可能存在多个不同的非零值。例如,统计后的数组有3、3、3,则正确;如果有3、2、3,则错误。 但是上述代码可能存在一个问题,比如当数组中多个非零值,其中有一个不同的情况。例如,数组中的元素是3,3,2,这时候,第一次遇到3,expected设为3,然后遇到第二个3没问题,遇到2时,发现不等于expected,返回false,正确。 但是,如果数组中的非零值的顺序是3,2,3,那么在遍历时,第一次expected设为3,第二个是2,这时候2不等于3,返回false,正确。 那这样这个代码的逻辑是对的? 是的,因为一旦有一个数不等于第一个遇到的非零数,就返回false,否则全部相等则返回true。 但这里有个问题,比如,如果数组中存在多个不同的非零值,例如,3和2,那么第一次设置expected为3,当遍历到2时,发现不等于,返回false。这样是对的。 那这个方法是正确的吗? 例如,假设字符串是“aabbcc”,每个字符出现两次。数组中的非零值都是2。遍历时,expected会被设置为第一个非零的2,后面的每个非零都等于2,返回true。 如果字符串是“aaabbbc”,次数是3,3,1。这时候第一次非零是3,后面遇到3没问题,遇到1时返回false,正确。 但是如果数组中的非零值的顺序是3,1,3,3,这时候第一次非零是3,后面的1会触发false,正确。 所以这个方法是正确的。 但是有没有例外情况? 比如,字符串中所有字符出现的次数都相同,但第一个非零的次数不是后面的次数?例如,数组中的非零元素是2,2,2,那么没问题。或者如果数组中的非零元素是1,1,1,那么也没问题。所以无论顺序如何,只要所有非零元素的值相同,就会返回true。 那这个方法是可行的。因此,这样的算法是正确的。 接下来,可能需要考虑一些特殊情况: - 空字符串:题目可能假设输入字符串非空,但需要处理的话,可以返回true还是false?比如,空字符串可能认为所有字符的出现次数相同(因为没有任何字符),但具体情况要看题目要求。但力扣的类似题目可能不会出现这种情况。 - 单字符字符串:比如“aaaaa”,返回true。 此外,用户的问题可能要求区分大小写?根据引用[4]中的代码,假设是小写字母。如果题目中的字符串可能包含其他字符,比如大写字母或其他符号,则需要调整数组的大小或者使用哈希表。 比如,如果字符串包含所有可能的ASCII字符,则可以使用一个大小为256的数组,或者用哈希表来统计次数。例如,在Java中,可以这样处理: 使用HashMap: public boolean checkFrequency(String s) { Map<Character, Integer> map = new HashMap<>(); for (char c : s.toCharArray()) { map.put(c, map.getOrDefault(c, 0) + 1); } int expected = -1; for (int count : map.values()) { if (expected == -1) { expected = count; } else if (count != expected) { return false; } } return true; } 这种方法更通用,适用于所有字符,而不仅限于小写字母。此时,若所有字符的出现次数相同,则返回true,否则false。 这可能更符合一般情况的需求,但根据引用[4]中的例子,可能题目中的输入是小写字母,因此数组方法更高效。但如果题目没有明确说明,可能需要更通用的方法。 综上,用户的问题的解决方法是: 统计每个字符的出现次数,然后检查这些次数是否全部相同。具体实现可以用数组(针对小写字母)或哈希表(针对所有字符)。 另外,用户提到的力扣题目可能是“1941. 检查是否所有字符出现次数相同”,这题的解法类似上述思路。例如,在Python中,可以使用Counter统计次数,然后取values集合,判断集合的大小是否为1。 例如: from collections import Counter def areOccurrencesEqual(s: str) -> bool: counts = Counter(s) return len(set(counts.values())) == 1 这样更简洁。但需要注意,如果所有值的次数相同,则集合的大小为1。例如,如果所有次数是2,集合是{2},返回True。 所以,在Python中,这样的代码可以解决问题。 总结:核心思路是统计次数,然后判断所有非零次数是否相同。可以通过数组、哈希表或Counter来实现。 根据用户提供的引用,特别是引用[4],其中使用了数组统计次数,但比较的是两个字符串的次数是否相同。而这里的问题是不同的,需要同一个字符串中各字符次数是否相同。所以,方法类似,但比较的是统计后的数组中的非零元素是否一致。 因此,最终的解决方案可以是: 使用数组统计各字符的出现次数,然后遍历数组中的非零元素,检查是否所有元素相等。 这样就能解决问题。现在我需要将这个过程用中文解释清楚,并给出对应的代码示例,同时确保使用正确的LaTeX格式,并生成相关问题。</think>要检查字符串中所有字符出现次数是否相同,可以通过以下步骤实现: ### 方法思路 1. **统计字符出现次数**:使用数组或哈希表记录每个字符的出现次数。例如,对于小写字母字符串,可用长度为26的数组实现$O(1)$空间复杂度[^4]。 2. **过滤非零次数**:仅关注实际出现过的字符次数。 3. **验证一致性**:检查所有非零次数是否相等。若存在不同值则返回`false`,否则返回`true`。 ### 代码实现 #### 数组法(适用于小写字母) ```python def are_occurrences_equal(s: str) -> bool: count = [0] * 26 for c in s: count[ord(c) - ord('a')] += 1 # 提取非零次数 frequencies = [freq for freq in count if freq != 0] # 检查是否所有次数相同 return all(f == frequencies[0] for f in frequencies) ``` #### 哈希表法(通用字符) ```python from collections import Counter def are_occurrences_equal(s: str) -> bool: counts = Counter(s) return len(set(counts.values())) == 1 ``` ### 复杂度分析 - **时间复杂度**:$O(n)$,需遍历字符串和统计结构。 - **空间复杂度**:数组法为$O(1)$(固定26长度),哈希表法为$O(k)$($k$为不同字符数)。 ### 示例验证 - 输入`"abacbc"`,统计次数为`{'a':2, 'b':2, 'c':2}`,返回`true`。 - 输入`"aaabb"`,统计次数为`{'a':3, 'b':2}`,返回`false`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值