算法题一:统计一个整数数组中只出现一次的数字,其余数字的出现次数均为两次。
拿到这道题的第一反应就是使用辅助哈希的方式,统计每一个字符的出现次数,最后在遍历哈希表取出出现次数为一的数字即可。这个方法是可行的,但是时间效率相对偏低。
代码如下:
class Solution {
public int singleNumber(int[] nums) {
Map<Integer,Integer> map = new HashMap<>();
for(int num:nums){
if(map.containsKey(num)) map.put(num,map.get(num)+1);
else map.put(num,1);
}
for(int num:map.keySet()){
if(map.get(num) == 1) return num;
}
return 0;
}
}
看了题解之后,get到一种新的解法:异或运算,两个相同的数字异或的结果是0,而0和x异或的结果是x,因此使用这个特性我们就可以让数组中的每一个元素依次进行异或运算,最终得到的结果就是剩下的那一个只出现一次的数字。因为题目中已经规定了其他数字出现的次数只能是2,因此出现次数为2的数字将全部被消除。
代码如下:
class Solution {
public int singleNumber(int[] nums) {
int x = 0;
for (int num : nums) // 1. 遍历 nums 执行异或运算
x ^= num;
return x; // 2. 返回出现一次的数字 x
}
}
题目二:给定一个数字,计算出其二进制位中有几个1。
这道题我的第一思路仍然是暴力解法将这个数字转换为二进制之后,再统计其1的个数,但没有去代码实现,感觉很麻烦。
于是看了题解之后get到一种新的解法,让n与1相与,如果结果为1,证明n的二进位的最后一个数字是1,如果结果为0,那么n的最后一个二进制位上的数字位0。此时让n右移一位,继续相同的操作,统计1的个数即可。
代码如下:
class Solution {
public int hammingWeight(int n) {
int res = 0; //记录1的个数,使用按位与运算以及无符号右移的方式
while(n!=0){
res += n&1;
n>>>=1;
}
return res;
}
}
对这类数学计算的题型的理解:
数字在计算机中的存储方式都是二进制的形式,而我们在思考问题时总是会习惯性的先入为主按照十进制的方式进行思考,而忽略了很多方便的二进制运算方式。
MySQL
联合查询:union 和 union all 关键字;
eg :
select * from A where ... union [all] select * from A where ... ;
使用 union [all] 时,两条查询语句返回的列数必须是相同的,否则会报错;其次,使用 union 会带一个去重的操作;
比如我们要从学生表中查找出 age 大于18 岁的学生信息,以及 gender 为男的学生信息;
select * from Student where age > 18
union [all]
select * from Student where gender = '男';
注意,只要满足其一个条件的数据就应该被查出来,如果使用 union all 那么如果有一个学生同时满足两个条件就会在查询结果中展示出两条相同的信息;而使用 union 则可以去重;
子查询:
单值子查询:子查询的结果只包含一个值,即为某一行某一列的一个值。常用的关键字 =、 <>、 <、 <=、 > 、>=
eg:
select * from A where age = (select age from B where ...);
列子查询:子查询的额结果为一列;常用的关键字 in、not in、all、any、some
select * from A where id in(select id from B where ... );
行子查询:子查询的结果为一行,可以有多列;
eg:
select * from A where (course_id,mathGrade) = (select course_id,mathGrade from course where ...);
表子查询:子查询的结果为一张表,常用于父查询的 from 或者 where 关键字之后;
eg:
select * from (select name,gender from A where ... ) where ... ;
操作系统——死锁
死锁的概念:当两个及其以上的进程无休止地等待获取同一个资源时,即发生了死锁。
死锁产生的四个必要条件(四个条件必须同时发生才会产生死锁):
互斥条件:同一个资源同一时刻只能被一个进程持有;
持有等待条件:进程想获取其他资源时,手里的资源不能提前释放,并且还要等待另一个资源;
环路等待条件:进程 A 持有资源 1 ,它需要获取资源 2;而进程 B 此时持有资源 2,它需要获取资源 1;
不可剥夺条件:进程已经占用的资源不能被其他进程剥夺;
如果想要避免死锁的产生,那么就破坏上述的任意条件即可;如资源的有序分配、当一个进程等待其他资源过久时,可以提前释放自己已经占有的资源供其他进程使用;