优化是靠的退出时机,当除出来的数已经小于除数时,说明后续的已经不需要继续做了,并且如果除出来的余数为0,说明这两个数都是正因子
class Solution {
public boolean checkPerfectNumber(int num) {
int ans = 1;
if(num == 1){
return false;
}
for(int i = 2;i<num;i++){
int num2 = num / i;
if(num2 <= i){
break;
}
if(num % i == 0){
//可以找到两个正因子
ans += i;
ans += num2;
}
}
if(ans == num) return true;
return false;
}
}
如果不是快乐数,他在循环的过程中会重复某个值,这就导致他无法回到1
class Solution {
public boolean isHappy(int n) {
//中途若出现循环 则结束
HashSet<Integer> set = new HashSet<Integer>();
while(n != 1){
n = getNext(n);
if(set.contains(n)){
return false;
}
set.add(n);
}
return true;
}
public int getNext(int n){
int sum = 0;
while(n != 0){
int s1 = n%10;
sum+=s1*s1;
n = n/10;
}
return sum;
}
}
我的解法(暴力枚举)
class Solution {
public List<String> generateParenthesis(int n) {
HashSet<String> set = new HashSet<String>();
set.add("()");
//滑动窗口
for(int i = 1;i<n;i++){
HashSet<String> newSet = new HashSet<String>();
for(String s : set){
newSet.add("("+s+")");
for(int j = 0;j<=s.length();j++){
newSet.add(s.substring(0,j)+"()"+s.substring(j,s.length()));
}
}
set = newSet;
}
return new ArrayList(set);
}
}
这个题我更愿意用回溯,因为动态规划的最优子结构不好找 不过目前暂时不太会回溯,先贴个答案
class Solution {
List<String> res = new ArrayList<>();
public List<String> generateParenthesis(int n) {
if(n <= 0){
return res;
}
getParenthesis("",n,n);
return res;
}
private void getParenthesis(String str,int left, int right) {
if(left == 0 && right == 0 ){
res.add(str);
return;
}
if(left == right){
//剩余左右括号数相等,下一个只能用左括号
getParenthesis(str+"(",left-1,right);
}else if(left < right){
//剩余左括号小于右括号,下一个可以用左括号也可以用右括号
if(left > 0){
getParenthesis(str+"(",left-1,right);
}
getParenthesis(str+")",left,right-1);
}
}
}
当0<=j 当i-j<=j<=i时(两头变),此时可以使用单调队列维护状态:
假设这个栈是单调减的,头部的元素最大,则可以这样定义:如果头部index过期,则头部出,元素从尾部进,如果他遇到了比进去的元素更小的元素,则可以说明队列中元素不需要了(只需要最大的,如果进的那个元素已经大于队列尾部的元素,说明尾部的元素已经轮不到前面了)
这个解法并不只是在DP中作优化,本身单调队列也可以做一种解法
如滑动窗口最大值问题,就可以用单调队列代替查找,每一次循环将会减少k此循环,从O(mk) -> O(m)
一种只加载需要的页的技术,常常用于虚拟内存系统
从未访问的那些页从不加载到物理内存中
当调用不存在在内存中的页面时,将会发生缺页错误
缺页错误的解决方法如下:
缺页发生动作如下:
缺页处理时间主要由三部分构成:
这种算法很需要降低缺页的错误率
由于移动操作系统内存较小,所以不支持交换
页面共享,有可能绕过请求调页(如fork函数),这种情况可以采用写时复制技术,让进程在最开始拥有一样的副本,意味着当进程写入了共享页面,就创建共享页面的副本
页面置换有多种算法,这个算法是当发生缺页错误时,发现了空闲帧列表没有空闲位置,这时候需要换出一个空闲位置,这个位置如何去找的不同策略。不同的算法效率不同。
选择最旧的页面更新
性能不太理想 可能可以和其他算法配合使用 比如页面缓冲算法 不过这个算法理解很简单
最优置换可以说是最好的算法,但是由于很难找到这个整体的最优解,所以一般很难实现。他的思想是置换最长时间不会使用的页面,这个最长是根据全局而言
这个算法一般用于比较其他的算法,毕竟这个是最优的
使用的最多的算法,只看局部上的最少使用,并换掉他。(时间上向后看的最优页面置换算法)
这种算法在硬件层面上需要一定的支持,对于硬件来说,要确定由上次使用时间定义的帧的顺序。
由于很少有操作系统可以提供LRU的硬件支持,所以使用近似LRU算法,这个算法近似于LRU,通过检查引用位来确定哪些页面被使用,用引用位来代替时间定义的帧序。
页面置换算法还有很多,基于计数的页面置换是为每个页面引用次数保存一个计数器
置换有最小计数的页面,策略:积极使用的页面拥有较大的计数
置换有最小计数的页面,策略:最小的页面是刚刚进入并且没有被使用频繁
这不是一个页面置换算法,而是另外一个策略(措施):系统保留一个空闲帧缓冲池,当出现缺页错误,会选择一个牺牲帧。在写出之前,所需页面就可以读到来自缓冲池的空闲帧,这样可以让程序更加快速的启动。当牺牲帧以后被写出,它会被添加到空闲帧池