LeetcodeDay32:中等题的一天

36.有效的数独

在这里插入图片描述
其实就是想问你如何一次遍历筛选3个条件,行筛选和列筛选可以很容易就明白了能够同时筛选,[i][j],[j][i]即可。问题就是33的格子如何同时筛选。
设行索引变量为 i ,当 i < 3 时,i/3 = 0,当 3< i < 6 时,i/3 = 1,当6<i<9 时,i/3 = 2,列变量 j 同理。 那么取左上角3
3格子,则有 i<3,j<3 , Array[i/3][j/3] => Array[0][0],那么33总共九个数字,所以再加一个数组(也可以二维加哈希表),即Array[0][0][0-8] 就可以表示左上角33的9个数字。九个小的九宫格的区域就可以用对应的二维数组的九个地址一一对应了。因为题目说了是要看到一个小的九宫格是否有重复的数字。
示例 i = 5, j = 6 , 值是 9 ,则标记 Array[5/3 = 1][ 6 / 3 = 2][9-1] = 1 (1只是是标识符,没有数字含义)。 那么如果遇到 i = 4, j = 8,值是9 ,则判断时发现 Array[4/3 = 1][ 8 / 3 = 2][9-1] == 1 ,即产生了冲突。

class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& board) {
        int rows[9][9];
        int columns[9][9];
        int subboxes[3][3][9];       
        memset(rows,0,sizeof(rows));
        memset(columns,0,sizeof(columns));
        memset(subboxes,0,sizeof(subboxes));
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                char c = board[i][j];
                if (c != '.') {
                    int index = c - '0' - 1;
                    rows[i][index]++;
                    columns[j][index]++;
                    subboxes[i / 3][j / 3][index]++;
                    if (rows[i][index] > 1 || columns[j][index] > 1 || subboxes[i / 3][j / 3][index] > 1) {
                        return false;
                    }
                }
            }
        }
        return true;
    }
};

3.无重复字符的最长字串

在这里插入图片描述
滑动窗口。比较值得说道的一点是,左指针并不需要依次递增,即多了很多无谓的循环。 发现有重复字符时,可以直接把左指针移动到第一个重复字符的下一个位置即可。用这个举例:a b c d e f c g h,重复字符是 c。

官网答案:左指针指向 a,右指针指向 f 时,f 后面字符就是 c,即重复字符,这时开始收缩窗口,依次移动左指针,直到 d ,然后移动 右指针,即,左指针是依次移动。但 [a,f] 区间内已不可能有比该区间更长的字符串,左指针从 a 依次 移动到 d,中间的循环都无意义,可直接把左指针移动到 d,然后继续移动 右指针。
结论:缓存下每个字符及其位置,当出现重复字符时,直接左指针移动到重复字符的后一个位置,可理解为跳跃式收缩窗口,即可减少循环。
针对 abcdefagh 的情况,由于重复字符是 a,所以当右指针指向 a 时,左指针会移动到 b,没有发生跳跃,还是正常收缩窗口。
这里还有一点需要说明,官网答案在收缩窗口移动左指针时,会依次移除左边的字符。但如果跳跃式移动串口,不会移除左边的字符。 比如: a b c d e f c a e f g h,当窗口移动为 [ a b c d e f ] 时,下一位字符为重复字符 c ,然后窗口收缩为 [ d e f c ],但此时因为是跳跃式收缩,哈希缓存表 并不能 移除 a b ,即缓存表是 { a:0 , b:1 ,d:3 ,e: 4 ,f :5 ,c: 6 } ,即 最左边 [ a ,b ] 还在缓存表内。 此时,右指针再移动一次,指向 a ,注意当前左指针是 指向 d 索引为 3, 缓存表判断出有重复字符 a ,这是需要判断索引大小,只有大于 3 时,才移动左指针,否则忽略。即,虽然[ a, b]还在缓存表内,但是已经变为无效缓存,会忽略掉。最后可以直接将最新的重复数字的下标直接更新。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char, int> map;
        int res = 0;
        for(int i = 0, j = 0; j <s.size(); j++){
            if (map.find(s[j]) != map.end()){
                if (map.find(s[j])->second > i) i = map[s[j]];
            }
            res = max(res, j-i+1);
            map[s[j]] = j+1; //直接更新最新的下标
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值