“21 天好习惯”第一期-7

目录 

数据库知识点整理:

leetcode每日一题:

难题积累:


数据库知识点整理:

        3.4 : 数据查询.

                模板: 

select -- {基本表中存在的列明 , 且存在下层调用的表格}
from -- {引用的表格}
where -- {设置选择的条件}
group by -- {以 列名 来分类 , 同一个常量只能出现一次}
have -- {对分类后的设置选择的条件}
order by -- {排序 , asc | desc}

       子函数 :

                cast ( num  as int ) : 取整 ( cast ( price * 0.8 as int ) .

                distinct col : 删除 col 重复常量 ( select distinct book_no ) .

                top n col : 输出列表中前 n 行 ( select top 3 *  ) . 

                比较运算符 : = , > , < , >= 或 !< , <= 或 !> , != 或 <> , not .

                between a and b : 在 a 和 b 之间 ( 类 -> a <= x <= b ) .

                in : 处于集合中 .

                like : 字符串匹配 ( like '  ' ) .

                % : 之后可以跟任意个 任意的字符 . 

                _ : 之后可以跟一个 任意的字符 .

                and : 连接两个条件 , 表示 ( a = 'a' and b = 'b' ) .

                or : 连接两个条件 , 表示 (a = 'a' and b = 'b' ) . 

                count : 统计该列 常量 的个数 . 

                distinct : 去除重复的常量 .

                sum : 常量的总和 . 

        (sum 和 count 的区别) : 假设 col 列存在 : 1 , 2 , 3 , 4. 那么count -> 4 , 而sum -> 10 . 

                avg : 计算平均值 ( sum对应的平均值 . 

       3.4.1 : 单表查询. 

                快速的将表中所有属性列都选出来的方法: select * .

                select 子句中可以是表中的属性列 , 也可以是表达式 (price * 0.8 .

                select book_name 书名 ( 给book_name列命名 .

                确定集合 where col in ('  ') .

                匹配串模板:

  实例                        效果

like '王%' -- -> 搜索以'王'开头的所有字符串 (王啊三 , 王五 .

like '%三' -- -> 搜索以'三'结尾的所有字符串 (这是三 , 王三 .

like '%三%' -- -> 搜索含有'三'这个字符的所有字符串 .

like '_三' -- -> 搜索只含有2个字符 , 且第二个字符为'三' 的字符串

like '[张,王]%' -- -> 分配

like '[^ 张,王]%' 00 -> ^表示非

                空间查询为 -> is null , 而不是 = null .

leetcode每日一题:

次元门

一道脑筋急转弯 , 实际上只有三种交叉的图像.

class Solution {
public:
    bool isSelfCrossing(vector<int>& distance) {
        int n = distance.size();

        if(n < 4) return false;

        for(int i = 0;i < n;i ++){
            if(i + 3 < n && distance[i + 2] <= distance[i] && distance[i + 3] >= distance[i + 1]) return true;
            if(i + 4 < n && distance[i] + distance[i + 4] >= distance[i + 2] && distance[i + 1] == distance[i + 3]) return true;
            if(i + 5 < n && distance[i + 2] >= distance[i + 4] && distance[i + 3] > distance[i + 1] && distance[i] + distance[i + 4] >= distance[i + 2] && distance[i + 5] + distance[i + 1] >= distance[i + 3]) return true; 
        }

        return false;
    }
};

难题积累:

次元门

解法1: bfs 

(\\v\\) 自己的错误代码.

class Solution {
public:
    bool canCross(vector<int>& stones) {
        int n = stones.size();
        
        bitset<2005>bit;
        unordered_map<int , int>ma;
        for(int i = 0;i < n;i ++) ma[stones[i]] = i;

        queue<pair<int , int>>que;
        if(ma.count(stones[0] + 1)) que.push({stones[0] + 1 , 1}) , bit[ma[stones[0] + 1]] = 1;

        while(!que.empty()){
            // auto [ide , val] = que.front();
            int ide = que.front().first , val = que.front().second;
            que.pop();

            if(ide == stones[n - 1]) return true;
            
            for(int i = -1;i <= 1;i ++){
                if(ide + val + i == stones[n - 1]) return true;
                if(!bit[ma[ide + val + i]] && ma.count(ide + val + i) && ide + val + i > ide) 
                    que.push({ide + val + i , val + i}) , bit[ma[ide + val + i]] = 1;
            }
        }

        return false;
    }
};

题解:

class Solution {
public:
    bool canCross(vector<int>& stones) {
        if (stones[0] + 1 != stones[1]) { // 第一步只能从第一块石头跳一步,所以如果不成立直接返回false
            return false;
        }
        int n = stones.size();
        unordered_set<int> stoneSet; // 记录哪些单元格有石头,方便查找
        unordered_map<int, unordered_set<int>> visited; // 记录同一块石头跳i步的情况是否遍历过,用于剪枝
        for (int i = 0; i < n; i++) {
            stoneSet.insert(stones[i]);
            visited[stones[i]].insert(0);
        }

        queue<pair<int, int>> q;
        q.emplace(stones[1], 1);
        visited[0].insert(1);
        while (!q.empty()) {
            int curStone = q.front().first; // 当前所在石头
            int curStep = q.front().second; // 上一次跳的步数k
            q.pop();
            for (int i = 0; i < 3; i++) { // 遍历k - 1、k、k + 1三种情况
                int nextStone = curStone + curStep - 1 + i;
                if (nextStone == stones[n - 1]) {  // 目标石头等于最后一块石头
                    return true;
                }
                if (curStep - 1 + i > 0) {
                    if (nextStone < stones[n - 1] && // 目标石头必须小于最后一块石头,因为不能回头
                        stoneSet.count(nextStone) && // 目标石头必须存在
                        visited[nextStone].count(curStep - 1 + i) == 0) { // 用k - 1 + i步跳到目标石头的情况没有遍历过
                        q.emplace(nextStone, curStep - 1 + i);
                        visited[nextStone].insert(curStep - 1 + i);
                    }
                }
            }
        }
        return false;
    }
};

题解出处: growl-2

解法2: dp 动态规划

不想多说 , wa 了 n 次.

        二维dp: 第一维 表示当前所在的下标. 第二维 表示在当前下标位置的石头的 val 值.

        逆向思维: 当你可以走到下标 ide 时 , 那么两个石头之间(stones[ide] 和 stones[before]) 一定要有这个关系: 在下标为before的石头 的val 值 (stones[ide] - stones[before] , stones[ide] - stones[before] + 1 , stones[ide] - stones[before] - 1.) 其中一个存在.

        所以状态转移方程为: dp[i][val] = dp[j][val] || dp[j][val - 1] || dp[j][val + 1] || dp[i][val];

class Solution {
public:
    bool canCross(vector<int>& stones) {
        int n = stones.size();
        vector<vector<bool>>dp(n + 1 , vector<bool>(n + 1 , false));

        if(stones[0] + 1 != stones[1]) return false;
        dp[0][0] = true;
        
        for(int i = 1;i < n;i ++){
            for(int j = i - 1;j >= 0;j --){
                int val = stones[i] - stones[j]; //两个石头之间的差值.
                if(val > i) break;
                dp[i][val] = dp[j][val] || dp[j][val - 1] || dp[j][val + 1] || dp[i][val];
            }
        }

        for(int i = 1;i < n;i ++) if(dp[n - 1][i]) return true;

        return false;
    }
};

繁花落尽 心中仍有花落的声音 一朵一朵在无人的山间轻轻飘过.Day Seven -- 画船听雨眠.

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值