[日常刷题]leetcode D30

本文解析了LeetCode上的三道经典题目:FirstUniqueCharacterinaString、FindtheDifference和NthDigit,提供了C++实现的解决方案,并总结了XOR运算在求奇数个数问题中的应用。

387. First Unique Character in a String

Given a string, find the first non-repeating character in it and return it’s index. If it doesn’t exist, return -1.
Examples:

s = "leetcode"
return 0.

s = "loveleetcode",
return 2.

Note: You may assume the string contain only lowercase letters.

Solution in C++:

关键点:

  • 第一个非重复字符

思路:

  • 因为是字母所以就很有限了,大概思想是先扫描一遍string s,记录其中的字母个数,然后再扫描一遍记录判断其是否大小为1,是即为第一个非重复字符的下标。
int firstUniqChar(string s) {
        map<char, int> maps;
   
        for(auto ch : s){
            map<char, int>::iterator it = maps.find(ch);
            if (it != maps.end()){
                ++maps[ch];
            } else{
                maps[ch] = 1;
            }    
        }
        
        size_t size = s.size();
        for(int i = 0; i < size; ++i)
            if(maps[s[i]] == 1)
                return i;
        return -1;      
    }

389. Find the Difference

Given two strings s and t which consist of only lowercase letters.

String t is generated by random shuffling string s and then add one more letter at a random position.

Find the letter that was added in t.

Example:

Input:
s = "abcd"
t = "abcde"

Output:
e

Explanation:
'e' is the letter that was added.

Solution in C++:

关键点:

  • 多余字母

思路:

  • 实际就是找另一个字符串中多出来的那个字母,我感觉我现在做这类题目已经有种惯性了,直接就是先扫描string s,记录其中每个字母的个数。然后再扫描一遍string t,将记录中对应字母个数-1,再判断是否小于0,是则找到了;
  • 然后看到了discuss里面的一个答案,让我又想起了XOR的用法,就是获取到奇数个个数的东西。

方法一:暴力扫描

char findTheDifference(string s, string t) {
        vector<int> characters(26,0);
        
        for(auto ch : s){
            ++characters[ch-'a'];
        }
        
        for(auto ch : t){
            if (characters[ch-'a'] == 0)
                return ch;
            else{
                if (--characters[ch-'a'] < 0)
                    return ch;
            }
        }
    }

方法二:XOR

char findTheDifference(string s, string t) {
        char res = 0;
        for(auto ch : s)
            res ^= ch;
        
        for(auto ch : t)
            res ^= ch;
        
        return res;
    }

400. Nth Digit

Find the n t h n^{th} nth digit of the infinite integer sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, …
Note:
n is positive and will fit within the range of a 32-bit signed integer (n < 2 31 2^{31} 231).

Example 1:

Input:
3

Output:
3

Example 2:

Input:
11

Output:
0

Explanation:
The 11th digit of the sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... is a 0, which is part of the number 10.

Solution in C++:

关键点:

  • 哈哈哈

思路:

  • 用一个数组存i位数字的第一个数字,然后用另外一个数组存i位数字的总位数。这两个数组需要自己初始化,因为范围是int所以这两个数组的大小并不大。基本算法大家自己列举几个就看出来规律了。然后根据输入的n判断属于哪个位数段,再计算出数字加偏移即可得出数字。看了下大家大致的思想都差不多,对于处理得到num[offset]有的直接转换成字符串得到,我的方法可能朴素了点,就直接是数字方法获取,所以自己写了获取num的offset位的方法。
位数第一个数字总个数总位数
i 1 0 i − 1 10^{i-1} 10i19 * 1 0 i − 1 10^{i-1} 10i19 * 1 0 i − 1 10^{i-1} 10i1 * i
class Solution {
public:
    int getDigit(int num, int index, int totalDigit){
        if (index > totalDigit)
            return -1;
        
        int i = totalDigit - index;
        int count = 0;
        while(num){
            if (count == i)
                return num % 10;
            num /= 10;
            ++count;   
        }
    }
    
    int findNthDigit(int n) {
        // startNum[i] 表示当数字位数为i时第一个数 eg.startNum[1] = 1
        vector<int> startNum{0};
        // totalDigit[i] 表示当数字位数为i时总位数 eg.totalDigit[1] = 9
        vector<long long> totalDigit{0};
        
        long long sumDigit = 9;
        long long num = 1;

        for(int i = 1; num < INT_MAX; ++i){
             startNum.push_back(num);
             totalDigit.push_back(sumDigit);
             sumDigit = 9 * pow(10,i) * (i+1);
             num = pow(10,i);
        }

        size_t size = totalDigit.size();

        for(int i = 1; i < size; ++i){
            long long tmp = n - totalDigit[i];
            if (tmp <= 0){
                int index = n / i;  // 第几个数
                int offset = n % i; // 数字中第几位
                // 计算数字

                num = startNum[i] + index;
                if (i == 1)
                    --num;

                if (offset == 0){
                    if (i == 1)
                        return num;
                    return getDigit(num-1,i,i);
                } else{
                    return getDigit(num,offset,i);
                }
            }
            n -= totalDigit[i];
        }
    }
};

小结

今天前面两题基本没花什么大时间,主要最后一题的逻辑处理部分花了不少时间,对于index的处理以及offset的处理。然后再就是long long越界问题的处理。然后对于XOR的方法有加深了印象。

知识点

  • XOR求奇数个数的问题
### 如何用C++在LeetCode的最佳实践 #### 使用C++进行LeetCode编程练习的重要性 由于C++设计感强,STL作为其泛型编程的杰出代表作,在掌握了C++基本语法以及STL中的容器与算法之后,已经具备了解决大多数编程挑战的基础[^1]。 #### 资源推荐 为了更高效地利用C++在LeetCode平台上进行训练,《剑指 Offer》这本书籍及其配套的Python、Java和C++解代码库是一个很好的起点。此资源不仅提供详细的解答思路,还涵盖了多种实现方式,有助于加深对问的理解[^2]。 #### 平台特点 LeetCode平台本身拥有大量精心挑选并按难度分级编排的问集,这些问广泛涉及各种类型的算法和数据结构,非常适合用来提高个人技能水平。更重要的是,这些目通常反映了实际工作中可能遇到的情况或是编程比赛中的典型考形式[^3]。 #### 策略 当准备着手解决问时,建议先浏览一下该所关联的知识领域标签(例如:“数组”,“字符串”,“链表”),这样可以帮助快速定位所需复习的概念和技术要点。针对不同的数据结构类别采取相应的学习方法: - **链表**:重点在于理解指针的工作原理及如何有效地管理内存分配; - **树和图**:则需深入研究递归遍历和其他高级搜索技术来应对更加复杂的逻辑关系[^4]。 ```cpp // 示例:简单的二分查找函数实现 #include <vector> using namespace std; int binarySearch(const vector<int>& nums, int target) { int left = 0; int right = nums.size() - 1; while (left <= right) { int mid = left + (right - left) / 2; // 防止溢出 if (nums[mid] == target) return mid; else if (nums[mid] < target) left = mid + 1; else right = mid - 1; } return -1; // 如果找不到目标,则返回-1表示未找到 } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值