LeetCode(编程基础0到1 --篇)c++

目录

一、回文数 9(不是本篇内容,但也是最近写的,也就一起总结啦)

1.正负数怎么判断

2.怎么将数字倒过来,判断是不是回文数

二、找不同 389

三、重复的子字符串 459

 方法一

解释:

举例:

证明充要性:

方法二

解释:

举例:

四、交替合并字符串 1768

解释:

五、找出字符串中第一个匹配的下标 28

解释: 

六、移动零 283

解释:

七、有效的字母异位词 242

方法一

解释:

八、数组元素积的符号 1822

九、加一 66

解释:

十、判断能否形成等差数列 1502

十一、单调数列 896

 方法一

解释:

方法二:

十二、最后一个单词的长度 58

 方法一

解释: 

方法二

解释: 

十三、罗马数字转整数 13

官网题解

 解释:

十四、棒球比赛 682

 方法一

解释:

十五、转化成小写字母 709

 方法一

方法二

 解释:

方法三

十六、最富有客户的资产总量 1672

 方法一

解释: 

方法二

解释:

十七、机器人能否返回原点 657

 方法一

 解释:

方法二

 解释:

十八、矩阵对角线元素的和 1572

 方法一

 解释:

方法二

 方法三

 解释:


 小伙伴们,好啊!从今天起,本篇内容更新leetcode《编程基础0到1》。自己也在边走边学,希望我可以帮助到大家。

一、回文数 9(不是本篇内容,但也是最近写的,也就一起总结啦)

1.正负数怎么判断

直接判断如果是负数就直接false

if (x<0) return false;

2.怎么将数字倒过来,判断是不是回文数

sum肯定要经历三轮*10,所以现在里面乘。这个是我之前错的代码,就是在比原数多了一个数量级。

sum=n%10;
sum*=10;
n/=10;

下面这个是正确的代码。

long long int sum=0;
while(n!=0){
    sum=sum*10+n%10;
    n/=10;
}   

下面来一个正确的完整代码。时间79.3% 内存51.47%

class Solution {
public:
    bool isPalindrome(int x) {
        if (x<0) return false;
        int n=x;
        long long int sum=0;
        while(n!=0){
            sum=sum*10+n%10;
            n/=10;
        }
        return x==sum;  
    }
};

转化成字符串 时间 79.03% 内存23.41%

class Solution {
public:
    bool isPalindrome(int x) {
        string s=to_string(x);
        return s==string(s.rbegin(),s.rend());
    }
};

二、找不同 389

这个sum是int类型,之所以能和string类型相加减,是因为本质上是 ASCII值想加减。

时间 100% 内存 91.78%

class Solution {
public:
    char findTheDifference(string s, string t) {
        int sum=0;
        for(auto i:t) sum+=i;
        for(auto i:s) sum-=i;
        return sum;
    }
};

这个是位运算,其中用到了^异或运算符,即相同为0,不同为1。时间 100% 内存56.27%

class Solution {
public:
    char findTheDifference(string s, string t) {
        int sum=0;
        for(auto i:t) sum^=i;
        for(auto i:s) sum^=i;
        return sum;
    }
};

三、重复的子字符串 459

 方法一

 这个方法   时间  64.41%   内存  54.67%

    bool repeatedSubstringPattern(string s) {
        return (s + s).find(s, 1) != s.size();
    }

解释:

我们将两个字符串串起来,从索引值1开始查找,查找s,返回的是第一次找到s的索引值。记住这时's+s’已经将索引值0的数删掉了。如果这时候索引值不是原来字符串长度,就说明是true.

举例:

s='ababab',s+s='abababababab',find之后s+s字符串就变为了‘bababababab’。我们会在索引位置 1 找到第一个 "ababab",因此 find 返回 1

证明充要性:

正如上面这个例子,s+s变成了‘bababababab’,当查找s时,已经用到下面一个s的首值了,后面肯定是循环的,重复的。如果想不懂,就n个s想加,一直重复下去,就可以啦。

这个代码有点难懂!!!小伙伴们好好品味!!!哈哈哈哈哈哈

方法二

 这个方法   时间  64.66%   内存  89.78%

class Solution {
public:
    bool repeatedSubstringPattern(string s) {
        int n = s.length();
        for (int len = 1; len <= n / 2; len++) {
            if (n % len == 0) {
                bool isRepeated = true;
                for (int i = len; i < n; i++) {
                    if (s[i] != s[i - len]) {
                        isRepeated = false;
                        break;
                    }
                }
                if (isRepeated) {
                    return true;
                }
            }
        }
        
        return false;
    }
};

解释:

如果s是重复的字符串,必定是长度一半的任何数的倍数。如果不是,直接false。这个可以举例说明。s='ababab',那么6是1,2,3的倍数。如果s='aaa',那3是1的倍数,这都是毋庸置疑的。下面设置一个布尔数默认为true,从1开始到最大重复子串长度(n/2)并于后面所有的相应字符串比较,不相等就false,接着len+1,接着比对,如果到最大长度还找不到就直接false出去,否则就true。

举例:

s='ababab',先判断6是1,2,3的倍数,接着就判断最大子串长度,先是s[1]='b'  != s[0]='a',直接退出,接着下一轮循环。s[2]='a'  == s[0]='a',所以接着下面匹配,s[3]='b' == s[1]='b',下面在不断匹配,最后判断成功,返回true。

四、交替合并字符串 1768

 这个方法  时间  40.39%  内存  85.80%

class Solution {
public:
    string mergeAlternately(string word1, string word2) {
        string ans;
        int i=0,j=0;
        int len1 = word1.length(), len2 = word2.length();
         while (i < len1 && j < len2) {
            ans += word1[i++];
            ans += word2[j++];
        }

        while (i < len1) {
            ans += word1[i++];
        }

        while (j < len2) {
            ans += word2[j++];
        }
        return ans;
    }
};

解释:

这个代码很简单,就是当比较这两个字符串长度,先合并,然后比较谁更长,长的追加到后面。

五、找出字符串中第一个匹配的下标 28

 这个方法  时间  100%  内存  54.53%

class Solution {
public:
    int strStr(string haystack, string needle) {
        int ans=haystack.find(needle);
        if (ans!=string::npos) return ans;
        else return -1;
    }
};

解释: 

先将找到的索引值设为ans,find函数在找不到指定值得情况下会返回string::npos,如果找到就是true,否则就是false。

这一题和上一题都可以用KMP算法,后面会单独出一期。

六、移动零 283

 这个方法  时间  89.53%  内存  22.17%

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int slow=0,fast=0;
        int n=nums.size();
        while(fast<n){
            if(nums[fast]!=0){
                swap(nums[slow],nums[fast]);
                slow++;
            }
            fast++;
        }
    }
};

解释:

双指针做法。现将两个指针设置为0,判断值为快指针,快指针要<n,如果快的不是0就交换,并且慢指针+1,否则只是快指针+1。

七、有效的字母异位词 242

方法一

这个方法 时间  93.37%  内存  49.32%

class Solution {
public:
    bool isAnagram(string s, string t) {
        if(s.length()!=t.length()) return false;
        int charFreq[128]={0};
        for(char c:s) charFreq[c]++;
        for(char c:t) charFreq[c]--;
        for(int i=0;i<128;i++){
            if(charFreq[i]!=0) return false;
        }
        return true;
    }
};

解释:

如果两个字符串长度不相等,就直接false。接着,定义字母重复次数,使用的是数组128位(ASCII  0-127),遍历两个字符串,在s中加字母次数,在T中减少次数,最后判断,如果这个次数为0就true,否则就是false。

方法二

这个方法  时间  25.98%  内存  72.78%

class Solution {
public:
    bool isAnagram(string s, string t) {
        sort(s.begin(),s.end());
        sort(t.begin(),t.end());
        return s==t;
    }
};

 这个也不需要解释吧,就是排序,后判断。

八、数组元素积的符号 1822

 时间4ms,击败86.91%,内存10.1 MB,击败5.73%

class Solution {
public:
    int arraySign(vector<int>& nums) {
        int sum=0;
        for(auto i:nums){
            if(i==0) return 0;
            else if(i<0) sum+=1;
        }
        if(sum%2==0) return 1;
        else return -1;
    }
};

就是统计正负数个数,不再详解啦。

九、加一 66

时间  100%   内存  71.89%

class Solution {
public:
    vector<int> plusOne(vector<int>& digits) {
        int n=digits.size();
        for(int i=n-1;i>=0;--i){
            if(digits[i]!=9){
                ++digits[i];
                for(int j=i+1;j<n;++j){
                    digits[j]=0;
                }
                return digits;
            }
        }
        vector<int>ans(n+1);
        ans[0]=1;
        return ans;
    }
};

解释:

从最右边的数开始循环,如果这个是不是9,就直接在这个数基础上+1,然后返回。如果是9,就一直遍寻到找到不是9的那个数,然后在这个数+1,然后后面的数置0。最后,如果全都是9的话,直接在设置一个ans,比原来的多一位数,使最前面置1,后面全是0。

十、判断能否形成等差数列 1502

 这个方法 时间  70.73%  内存   82.93%

class Solution {
public:
    bool canMakeArithmeticProgression(vector<int>& arr) {
        sort(arr.begin(),arr.end());
        int cha=arr[1]-arr[0];
        for(int i=0;i<arr.size()-1;i++){
            if(arr[i+1]-arr[i]!=cha) return false;
        }
        return true;
    }
};

排序并判断。这题比较简单就不详细解答了。

十一、单调数列 896

 方法一

时间 5.17%  内存  55.66%

class Solution {
public:
    bool isMonotonic(vector<int>& nums) {
        bool decrease=true;
        bool increase=true;
        for(int i=0;i<nums.size()-1;i++){
            if(nums[i+1]>nums[i]) decrease=false;
            else if(nums[i+1]<nums[i]) increase=false;
        }
        return decrease||increase;
    }
};

解释:

定义两个布尔型一个升一个降,遍历数组,如果后一个大于前一个,就不是递减。后一个小于前一个,就不是递增。最后用或运算符。

方法二:

时间  43.08%  内存   24.62%

class Solution {
public:
    bool isMonotonic(vector<int>& nums) {
        return is_sorted(nums.begin(),nums.end())||is_sorted(nums.rbegin(),nums.rend());
    }
};

这个使用的c++自带的函数,遍历两次数组,分别判断其是否为单调递增或单调递减。

十二、最后一个单词的长度 58

 方法一

时间 44.36%  内存  5.1%

这个方法是我刚开始想到的方法,效率不高,但是只能想到这个。

class Solution {
public:
    int lengthOfLastWord(string s) {
        s+=' ';
        vector<int>counts;
        int count=0;
        for(int i=0;i<s.size();i++){
            if(s[i]!=' '){
                count++; 
            }

            else {
                if(count!=0){
                    counts.push_back(count);
                }
                count=0;
            }

        }
        int n=counts.size();
        return counts[n-1];
    }
};

解释: 

第一句话在s后面加个字符串就是截断最后一个字符串。然后将每个字符串长度保存在数组里,取最后一个数组就可以啦。

方法二

时间 100% 内存  73.24%

这个方法是看了题解,由反向遍历想到的,比官方解答效率高。

class Solution {
public:
    int lengthOfLastWord(string s) {
        int count=0;
        int n=s.size();
        for(int i=n-1;i>=0;i--){
            if(s[i]!=' ') {
                count++;
            }  
            else if(count>0) break;       
        }
        return count;
    }
};

解释: 

就是一个if语句,如果不是空格,就+1,是空格的时候用下一个语句,break出去。最后返回。

十三、罗马数字转整数 13

 这一题拿到的时候真的没有思路,只能想到用很多if语句。但是最后也没有写,感觉太麻烦了。在官网找题解的时候,也是有点震惊的,我以为c++的类是摆设,因为我从来没用过类,都是用的类内函数,类外函数依然可以实现。但是这次实实在在用类了,第一次用到,记录一下,哈哈哈哈哈

官网题解

时间  81.67%  内存  37.59%

class Solution {
private:
    unordered_map<char,int>symbolValues={
        {'I',1},
        {'V',5},
        {'X',10},
        {'L',50},
        {'C',100},
        {'D',500},
        {'M',1000},
    };
public:
    int romanToInt(string s) {
        int ans=0;
        int n=s.length();
        for(int i=0;i<n;++i){
            int value=symbolValues[s[i]];
            if(i<n-1&&value<symbolValues[s[i+1]]){
                ans-=value;
            }
            else{
                ans+=value;
            }
        }
        return ans;
    }
};

 解释:

这个代码的核心,是前面字母对应的值要比后面的小,才是用减法。我是没想到(hahaha)

private 就是用一个map容器,将对应的字母和值记录下来。然后如果前面字母对应的值要比后面的小,用减法。否则用加法。

十四、棒球比赛 682

 方法一

class Solution {
public:
    int calPoints(vector<string>& operations) {
        vector<int>ans;
        for(int i=0;i<operations.size();i++){
            if(operations[i]=="C"){
                if(!ans.empty()){
                    ans.pop_back();
                }
            }
            else if(operations[i]=="D"){
                if(!ans.empty()){
                    ans.push_back(ans.back()*2);
                }
            }
            else if(operations[i]=="+"){
                if(ans.size()>=2){
                    ans.push_back(ans[ans.size()-1]+ans[ans.size()-2]);
                }
            }
            else{
                ans.push_back(stoi(operations[i]));
            }
        
        }
        int totalScore=0;
        for(int score:ans){
            totalScore+=score;
        }
        return totalScore;
    }
};

解释:

stoi()函数——将数字字符转化为为int类型输出。

如果是数字的话直接转化为int类型加入,如果是‘C’,判断数组不是空的然后删掉最后一个数字,如果是‘D’,判断数组不是空的然后加入最后一个数字的二倍,如果是‘+’,判断前面要有两个数,再将他们想加,加入数组。最后算总输出。

十五、转化成小写字母 709

 方法一

class Solution {
public:
    string toLowerCase(string s) {
        transform(s.begin(),s.end(),s.begin(),::tolower);
        return s;
    }
};

 这个方法是网上找的函数,大家可以去搜一搜。

方法二

class Solution {
public:
    string toLowerCase(string s) {
         for(int i=0;i<s.size();i++){
             if(s[i]>='A'&&s[i]<='Z'){
                 s[i]+=32;
             }
         }
         return s;
    }
};

 解释:

这个方法利用了在ASCII中,对应的小写字母比大写字母多32。

方法三

class Solution {
public:
    string toLowerCase(string s) {
         for(char &ch:s){
             ch=tolower(ch);
         }
         return s;
    }
};

 这个就是将遍历字符串,将大写转为小写。利用了tolower函数。

十六、最富有客户的资产总量 1672

 方法一

class Solution {
public:
    int maximumWealth(vector<vector<int>>& accounts) {
        int maxWealth=INT_MIN;
        for(auto &account:accounts){
            maxWealth=max(maxWealth,accumulate(account.begin(),account.end(),0));
        }
    return maxWealth;
    }
};

解释: 

int sum = accumulate(account.begin() , account.end() , 0);  

accumulate第一个参数为vector二维数组的开始,第二个是结尾,第三个参数是sum的初始值。

INT_MAX = 2^31-1,INT_MIN= -2^31

方法二

class Solution {
public:
    int maximumWealth(vector<vector<int>>& accounts) {
        vector<int>counts;
        int sum=0;
        for(int i=0;i<accounts.size();i++){
            for(int j=0;j<accounts[0].size();j++){
                sum+=accounts[i][j];
                counts.push_back(sum);
            }
            sum=0;
        }
    return *max_element(counts.begin(),counts.end());;
    }
};

解释:

这个先将每个人的总资产算出来,保存到数组里,然后再返回最大值。

十七、机器人能否返回原点 657

 方法一

class Solution {
public:
    bool judgeCircle(string moves) {
        int x = 0, y = 0;
        for (const auto& move: moves) {
            if (move == 'U') {
                y--;
            }
            else if (move == 'D') {
                y++;
            }
            else if (move == 'L') {
                x--;
            }
            else if (move == 'R') {
                x++;
            }
        }
        return x == 0 && y == 0;
    }
};

 解释:

这个方法就是利用了上下、左右是对立面。只要对立面方向走的步数一样就可以回到原点。

方法二

class Solution {
public:
    bool judgeCircle(string moves) {
    return count(moves.begin(),moves.end(),'U') == count(moves.begin(),moves.end(),'D')
               && count(moves.begin(),moves.end(),'L') == count(moves.begin(),moves.end(),'R');
    }
};

 解释:

count(moves.begin() , moves.end() , 'U')

count函数第一个就是计算数组开始值,第二个参数是结束值,第三个是要搜索的值。

 本质还是和方法一一样,不做赘述。

十八、矩阵对角线元素的和 1572

 方法一

第一遍自己写的,我以为中间会加两次,就奇偶分开写了,在积后面减去中间的数,不对。下面是改正版。

class Solution {
public:
    int diagonalSum(vector<vector<int>>& mat) {
        int sum=0;
        int n=mat.size()-1;
        for(int i=0;i<mat.size();i++){
            if(mat.size()%2==1){
                for(int j=0;j<mat.size();j++){
                    if(j==i||j==n-i){
                        sum+=mat[i][j];
                    }
                }
            }
            else{
                 for(int j=0;j<mat.size();j++){
                    if(j==i||j==n-i){
                        sum+=mat[i][j];
                    }
                }
            }
        }
    return sum;
    }
};

 解释:

这个很简单,抓住对角线方程就可以。y=x;y=n-x这两个方程的应用。

方法二

这个来个简化版的

class Solution {
public:
    int diagonalSum(vector<vector<int>>& mat) {
        int sum=0;
        int n=mat.size()-1;
        for(int i=0;i<mat.size();i++){

            for(int j=0;j<mat.size();j++){
                if(j==i||j==n-i){
                    sum+=mat[i][j];
                }
            }
            

        }
    return sum;
    }
};

 方法三

class Solution {
public:
    int diagonalSum(vector<vector<int>>& mat) {
        int n = mat.size(), sum = 0, mid = n / 2;
        for (int i = 0; i < n; ++i) {
            sum += mat[i][i] + mat[i][n - 1 - i];
        }
        return sum - mat[mid][mid] * (n & 1);
    }
};

 解释:

这个方法和上面两个方法差不多。但是他奇数矩阵中间算了两次,巧妙的用了按位与运算。n如果是奇数,就减,否则不减。

十九、矩阵置零 73

 方法一

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int m = matrix.size();
        int n = matrix[0].size();
        vector<int> row(m), col(n);
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (!matrix[i][j]) {
                    row[i] = col[j] = true;
                }
            }
        }
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (row[i] || col[j]) {
                    matrix[i][j] = 0;
                }
            }
        }
    }
};

解释:

就是遍寻数组,然后将是0的分别标记在一维数组里,然后再遍寻一遍数组,将其置0。

官网题解的方法二时间复杂度和空间复杂度都比方法一差,还不好理解。所以,我们就不做解释了。

二十、在区间范围内统计奇数数目 1523

 方法一

 时间868,啊哈哈哈,自己写的(苦涩的笑容)

class Solution {
public:
    int countOdds(int low, int high) {
        int count=0;
        if(low%2==1){
            for(int i=low;i<high+1;){
                i+=2;
                count++;
            }
        }
        else{
            for(int i=low+1;i<high+1;){
                i+=2;
                count++;
            }
        }
        return count;
    }
};

这个题一定要注意开始的数字是奇数还是偶数,奇数比偶数多一个。

方法二

class Solution {
public:
    int countOdds(int low, int high) {
        if(high%2==0 && low%2==0) return (high-low) / 2;
        else return (high-low) / 2 + 1;
    }
};

 哎,一样的思路,别人写的就是有简短,效率又高。

二十一、去掉最低工资和最高工资后的工资平均值

class Solution {
public:
    double average(vector<int>& salary) {
        double maxValue = *max_element(salary.begin(), salary.end());
        double minValue = *min_element(salary.begin(), salary.end());
        double sum = accumulate(salary.begin(), salary.end(), - maxValue - minValue);
        return sum / int(salary.size() - 2);

    }
};

 这个方法函数详解上面有,思路也很简单,就不赘述啦。

二十二、三角形的最大周长 976

 方法一

class Solution {
public:
    int largestPerimeter(vector<int>& nums) {
        int n=nums.size();
        sort(nums.begin(),nums.end());
        for(int i=n-1;i>=2;--i){
            if(nums[i]<nums[i-1]+nums[i-2]) return nums[i]+nums[i-1]+nums[i-2];
        }
        return 0;
    }
};

 主要突破点:

已经排序好了,只要后两个大于这个就可以构成三角形。

二十三、柠檬水找零 860

 

 方法一

class Solution {
public:
    bool lemonadeChange(vector<int>& bills) {
        int five=0,ten=0;
        for(auto b:bills){
            if(b==5) five++;
            else if(b==10) ten++,five--;
            else if(ten) five--,ten--;
            else five-=3;
            if(five<0) return false; 
        }

    return true;    
    }
};

 主要突破点:

另外找两个数,用于存储5元和10元的,并且付20元时,先花费10+5元的。

二十三、二进制求和 67

 方法一

class Solution {
public:
    string addBinary(string a, string b) {
        string sum;
        int t=0;
        for(int i=a.size()-1,j=b.size()-1;i>=0||j>=0;--i,--j){
            if(i>=0) t+=a[i]-'0';
            if(j>=0) t+=b[j]-'0';
            sum.push_back((t%2)+'0');
            t/=2;
        }
        if(t) sum.push_back(1+'0');
        reverse(sum.begin(),sum.end());
        return sum;
    }
};

解释:

这个a[i]-'0'是将a[i]转化为整数,同理下面的-‘0’’也是。但是这个两个不一样。

这是因为字符 '0' 到 '9' 是 ASCII 码表中连续的字符,因此字符减去 '0' 会得到它所代表的数字。例如,字符 '1' 减去 '0' 会得到整数 1,字符 '2' 减去 '0' 会得到整数 2,以此类推。

在这段代码中,a[i]-'0' 是将字符型的数字转换成了整数型的数字,以便进行二进制加法运算。同样地,b[j]-'0' 也是将字符型的数字转换成了整数型的数字。

在二进制加法中,(t%2)+'0'(t%2)-'0' 的结果是不同的。当 t%2 为 0 时,(t%2)+'0' 的结果是 '0',而 (t%2)-'0' 的结果是非法字符,因为不能将字符减去数字。所以,这个表达式不能简单地用 -‘0’ 替换。

方法二

class Solution {
public:
    string addBinary(string a, string b) {
        int al=a.size();
        int bl=b.size();
        while(al<bl){
            a='0'+a;++al;
        }
        while(al>bl){
            b='0'+b;++bl;
        }
        for(int j=a.size()-1;j>0;--j){
            a[j]=a[j]-'0'+b[j];
            if(a[j]>='2'){
                a[j]=(a[j]-'0')%2+'0';
                a[j-1]=1+a[j-1];
            }
        }
        a[0]=a[0]-'0'+b[0];
        if(a[0]>='2'){
            a[0]=(a[0]-'0')%2+'0';
            a='1'+a;
        }
        return a;
    }
};

 这个方法就是在短的前面补0,然后进行加减,如果>=2,就留下余数,最后还要判断【0】的数。

二十四、缀点成线 1232

 

class Solution {
public:
    bool checkStraightLine(vector<vector<int>>& coordinates) {
        if (coordinates.size() <= 2) {
            return true; 
        }
        
        int x0 = coordinates[0][0];
        int y0 = coordinates[0][1];
        int x1 = coordinates[1][0];
        int y1 = coordinates[1][1];
        
        for (int i = 2; i < coordinates.size(); i++) {
            int x = coordinates[i][0];
            int y = coordinates[i][1];
            
            if ((y1 - y0) * (x - x0) != (y - y0) * (x1 - x0)) {
                return false; 
            }
        }
        
        return true; 
    }
};

 主要突破口:

如果有一般式的话,太麻烦了,要判断x的变化量等不等于0,用两点式就可以避免。

二十五、找出并字棋的获胜者 1275

 

class Solution {
public:
    string tictactoe(vector<vector<int>>& moves) {
        int len = moves.size();
        vector<vector<int>> ans(4, vector<int>(3, 0));        
        if (len <= 4) return "Pending";
      
        for (int i = (len + 1) % 2; i < len; i += 2) {
            for (int j = 0; j < 2; j++) {
                ans[j][moves[i][j]] += 1; 
            }           
            if (moves[i][0] == moves[i][1]) {
                ans[2][0] += 1;
            }           
            if (moves[i][0] + moves[i][1] == 2) {
                ans[3][0] += 1;
            }
        }       
        for (const auto& i : ans) {
            for (int j : i) {
                if (j == 3 && len % 2 == 1) {
                    return "A";
                }
                if (j == 3 && len % 2 == 0) {
                    return "B";
                }
            }
        }       
        if (len == 9) {
            return "Draw";
        } else {
            return "Pending";
        }
    }
};

解释:

  1. 首先,代码检查moves数组的长度是否小于等于4,如果是,则返回"Pending",表示游戏尚未结束。

  2. 然后,代码创建一个4x3的二维整数数组ans,用于记录井字棋游戏中各个玩家的得分情况。

  3. 接下来,代码通过两个嵌套的循环遍历moves数组。外层循环从索引为(len+1)%2的位置开始,每次递增2,直到索引达到len-1。内层循环固定为两次迭代。

  4. 在内层循环中,代码根据moves数组中的值更新ans数组。具体地,对于每个内层循环迭代,代码将ans数组的第一维和第二维分别与moves数组的值进行比较,并根据比较结果更新ans数组对应位置的计数器。

  5. 接着,代码检查当前行的两个元素是否相等,如果相等,则将ans数组的第三维第一列对应的计数器加1。

  6. 然后,代码检查当前行的两个元素的和是否为2,如果是,则将ans数组的第三维第一列对应的计数器加1。

  7. 在完成对moves数组的遍历后,代码通过两个嵌套的循环遍历ans数组。外层循环遍历ans数组的每一行,内层循环遍历每一行的每个元素。

  8. 在内层循环中,代码根据ans数组的元素值进行逻辑判断。如果某个元素的值为3且moves数组的长度为奇数,则返回"A",表示玩家A获胜。如果某个元素的值为3且moves数组的长度为偶数,则返回"B",表示玩家B获胜。

  9. 如果代码执行到这里,说明moves数组的长度为9,即井字棋游戏已经结束。此时,代码返回"Draw",表示游戏平局。

  10. 如果代码执行到最后一行,说明moves数组的长度既不是4以下,也不是9,则返回"Pending",表示游戏尚未结束。

 两个for循环这个虽然后文好像没用到,但是还是很有用的

在这段代码中,通过内层的for循环遍历当前行的两个元素moves[i][j],并将ans[j][moves[i][j]]的值加1,表示对应位置的元素出现次数加1。

由于后续的判断依赖于对ans数组的访问,如果去掉这段代码,将无法正确统计和判断"X"和"O"的出现情况,从而导致函数返回的结果不正确。

因此,保留这段代码是必要的,以确保正确地统计每一行中每个元素的出现次数,并进行后续的判断和处理。

二十六、困于环中的机器人 1041

 

class Solution {
public:
    bool isRobotBounded(string instructions) {
        vector<vector<int>> direc {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
        int direcIndex = 0;
        int x = 0, y = 0;
        for (char instruction : instructions) {
            if (instruction == 'G') {
                x += direc[direcIndex][0];
                y += direc[direcIndex][1];
            } else if (instruction == 'L') {
                direcIndex += 3;
                direcIndex %= 4;
            } else {
                direcIndex++;
                direcIndex %= 4;
            }
        }
        return direcIndex != 0 || (x == 0 && y == 0);
    }
};

 解释:

x,y用于统计位置,direcIndex用于统计方向,最后如果方向只转了一圈或者原位置不动就是真的。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值