题目给你一个整数 num ,返回 num 中能整除 num 的数位的数目。
如果满足 nums % val == 0 ,则认为整数 val 可以整除 nums 。
示例 1:
123输入:num = 7输出:1解释:7 被自己整除,因此答案是 1 。
示例 2:
123输入:num = 121输出:2解释:121 可以被 1 整除,但无法被 2 整除。由于 1 出现两次,所以返回 2 。
示例 3:
123输入:num = 1248输出:4解释:1248 可以被它每一位上的数字整除,因此答案是 4 。
提示:
1 <= num <= 109
num 的数位中不含 0
解答123456789101112class Solution {public: int countDigits(int num) { int count = 0; int tmp = num; while(tmp){ count = (num%(tmp%10)==0)?count+1:count; ...
R1.1 敏感数据不可写入代码ID_plainSensitiveInfo :shield: security warning
代码中的敏感数据极易泄露,产品及相关运维、测试工具的代码均不可记录任何敏感数据。
示例:
12345678/** * My name is Rabbit * My passphrase is Y2Fycm90 // Non-compliant */#define PASSWORD "Y2Fycm90" // Non-compliantconst char* passcode = "Y2Fycm90"; // Non-compliant
将密码等敏感数据写入代码是非常不安全的,即使例中 Y2Fycm90 是实际密码的某种变换,聪明的读者也会很快将其破解。
敏感数据的界定是产品设计的重要环节。对具有高可靠性要求的客户端软件,不建议保存任何敏感数据,对于必须保存敏感数据的软件系统,则需要落实安全的存储机制以及相关的评审与测试。 ...
搜狗的开源项目中有一个非常重要的基础模块:线程池,代码只有300行代码
简介Workflow的大招:计算通信融为一体的异步调度模式,而计算的核心:Executor调度器,就是基于这个线程池实现的。可以说,一个通用而高效的线程池,是我们写C/C++代码时离不开的基础模块。
thrdpool代码位置在src/kernel/,不仅可以直接拿来使用,同时也适合阅读学习。
特点:
创建完线程池后,无需记录任何线程id或对象,线程池可以通过一个等一个的方式优雅地去结束所有线程(线程是对等的)
线程任务可以由另一个任务调起,线程池正在被销毁的时候也可以提交下一个任务
线程任务可以销毁这个线程池(行为是对等的)
前置知识为什么需要线程池?(其实思路不仅对线程池,对任何有限资源的调度管理都是类似的)
我们知道,C/C++常用的pthread或者std::thread就可以创建线程,实现多线程并行执行我们的代码。
但是CPU可以并行的线程数是固定的,所以真正并行执行的最大值也是固定的,过多的线程创建除了频繁产生创建的overhead以外,还会导致对系统资源进行争抢,这些都是不必要的浪费。
因此我们可以 ...
题目给你一个正整数 n ,请你返回 n 的 惩罚数 。
n 的 惩罚数 定义为所有满足以下条件 i 的数的平方和:
1 <= i <= n
i * i 的十进制表示的字符串可以分割成若干连续子字符串,且这些子字符串对应的整数值之和等于 i 。
示例 1:
1234567输入:n = 10输出:182解释:总共有 3 个整数 i 满足要求:- 1 ,因为 1 * 1 = 1- 9 ,因为 9 * 9 = 81 ,且 81 可以分割成 8 + 1 。- 10 ,因为 10 * 10 = 100 ,且 100 可以分割成 10 + 0 。因此,10 的惩罚数为 1 + 81 + 100 = 182
示例 2:
12345678输入:n = 37输出:1478解释:总共有 4 个整数 i 满足要求:- 1 ,因为 1 * 1 = 1- 9 ,因为 9 * 9 = 81 ,且 81 可以分割成 8 + 1 。- 10 ,因为 10 * 10 = 100 ,且 100 可以分割成 10 + 0 。- 36 ,因为 36 * 36 = 1296 ,且 1296 可以分割成 1 + 2 ...
经典书籍学习
未读从给处理器加电开始,直到你断电为止,程序计数器假设一个值的序列a0,a1,⋯ ,an−1
其中,每个 a~k~ 是某个相应的指令 I~k~ 的地址。每次从 a~k~到 a~k+1~ 的过渡称为控制转移(control transfer)。这样的控制转移序列叫做处理器的控制流(flow of control 或 control flow)。
系统也必须能够对系统状态的变化做出反应,这些系统状态不是被内部程序变量捕获的,而且也不一定要和程序的执行相关。比如,一个硬件定时器定期产生信号,这个事件必须得到处理。包到达网络适配器后,必须存放在内存中。程序向磁盘请求数据,然后休眠,直到被通知说数据已就绪。当子进程终止时,创造这些子进程的父进程必须得到通知。
现代系统通过使控制流发生突变来对这些情况做出反应。一般而言,我们把这些突变称为异常控制流(Exceptional Control Flow,ECF)。异常控制流发生在计算机系统的各个层次。比如,在硬件层,硬件检测到的事件会触发控制突然转移到异常处理程序。在操作系统层,内核通过上下文切换将控制从一个用户进程转移到另一个用户进程。在应用层,一个进程 ...
经典书籍学习
未读字符串、向量和数组using
有了using声明就不需要专门前缀去使用所需的名字了:
123456789#include <iostream>using std::cin;int main(){ int i; cin>>i; std::cout<<i; return 0;}
位于头文件的代码,一般来说不应该使用using声明,因为头文件的内容会拷贝到所有引用他的文件中去,如果头文件里有某个using的声明,那么每个使用该头文件都会有这个声明。
string
有时我们需要能在得到的字符串中保留输入时的空白符,这时应该用getline函数代替原来的>>运算符。
1234567int main(){ string line; while(getline(cin,line)){ cout<<line; } return 0;}
当把string对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运 ...
题目这里有 n 个一样的骰子,每个骰子上都有 k 个面,分别标号为 1 到 k 。
给定三个整数 n , k 和 target ,返回可能的方式(从总共 kn 种方式中)滚动骰子的数量,使正面朝上的数字之和等于 target 。
答案可能很大,你需要对 109 + 7 取模 。
示例 1:
1234输入:n = 1, k = 6, target = 3输出:1解释:你扔一个有 6 个面的骰子。得到 3 的和只有一种方法。
示例 2:
1234输入:n = 2, k = 6, target = 7输出:6解释:你扔两个骰子,每个骰子有 6 个面。得到 7 的和有 6 种方法:1+6 2+5 3+4 4+3 5+2 6+1。
示例 3:
123输入:n = 30, k = 30, target = 500输出:222616187解释:返回的结果必须是对 109 + 7 取模。
提示:
1 <= n, k <= 30
1 <= target <= 1000
解答这道题一看就是用动态规划
1234567891011121314151617181920class So ...
经典书籍学习
未读让自己习惯C++视 C++ 为一个语言联邦C++ 拥有多种不同的编程范式,而这些范式集成在一个语言中,使得 C++ 是一门即灵活又复杂的语言:
传统的面向过程 C:区块,语句,预处理器,内置数据类型,数组,指针。
面向对象的 C with Classes:类,封装,继承,多态,动态绑定。
模板编程 Template C++ 和堪称黑魔法的模板元编程(TMP)。
C++ 标准库 STL。
C++ 高效编程守则视情况而变化,程序设计没有银弹。
在软件工程的经典论文《没有银弹》中,银弹象征着一种特效的、一用就灵的方法。然而,这个词背后蕴含着一种深刻的含义,它揭示了软件工程的复杂性和解决问题的艰难性。
尽量用const enum inline来替换#define在原书写成的时候还没有诞生constexpr,现在一般认为应当用constexpr定义编译器常量来替代大部分的#fefine宏常量定义
常量
1#define ASPECT_RATIO 1.653
替代为:
1constexpr auto aspect_ratio = 1.653;
也可以定义成类的静态成员:
1234cla ...
第一次阅读源码,选择的是搜狗的workflow,这次阅读的是list
内核链表的结构123struct list_head { struct list_head *next, *prev;};
这里发现,链表中没有数据,只有前驱和后继指针
如果我们要使用到内核的链表结构,我们需要定义一个struct list_head{}类型的结构体成员对象就可以了
eg:
1234struct Task{ struct list_head entry_list; int val;}
链表初始化这里我只看第二种,即INIT_LIST_HEAD
12345static inline void INIT_LIST_HEAD(struct list_head *list){ list->next = list; list->prev = list;}
1234567891011121314#include "list.h"struct Task { struct list_head ent ...
经典书籍学习
未读还有两章太偏硬件了,后面再看吧,先进入第二大章的学习:在系统上运行程序。
继续我们对计算机系统的探索,进一步来看看构建和运行应用程序的系统软件。链接器把程序的各个部分联合成一个文件,处理器可以将这个文件加载到内存,并且执行它。现代操作系统与硬件合作,为每个程序提供一种幻象,好像这个程序是在独占地使用处理器和主存,而实际上,在任何时刻,系统上都有多个程序在运行。
本书的第二部分将拓宽你对系统的了解,使你牢固地掌握程序和操作系统之间的交互关系。你将学习到如何使用操作系统提供的服务来构建系统级程序,例如 Unix shell 和动态内存分配包。
链接(linking)是将各种代码和数据片段收集并组合成为一个单一文件的过程,这个文件可被加载(复制)到内存并执行。链接可以执行于编译时(compile time),也就是在源代码被翻译成机器代码时;也可以执行于加载时(load time),也就是在程序被加载器(loader)加载到内存并执行时;甚至执行于运行时(runtime),也就是由应用程序来执行。在早期的计算机系统中,链接是手动执行的。在现代系统中,链接是由叫做链接器(linker)的程序自 ...