笔者自述:
一直有一个声音也一直能听到身边的大佬经常说,要把算法学习搞好,一定要重视平时的算法学习,虽然每天也在学算法,但是感觉自己一直在假装努力表面功夫骗了自己,没有规划好自己的算法学习和总结,因为后半年也该找实习了,所以每日的算法题要进行恶补,勤能补拙,因此有了这一个算法日记系列;
必读: 大佬你好,感谢您的阅读,这篇文章是我的算法笔记,方便我每日回顾;
为了不耽误您的时间,我把本篇日记的考点方向和算法知识总结列出来,如果对您有需要要就向下继续阅读
也希望对您有帮助,和您一起通关算法!致谢
算法语言:java
题目来源:力扣–书本–图解算法数据结构,可以在力扣中搜索相关题名找到更多解法和大神方法
本文知识点汇总:
-
ArrayList和LInked两个列表的区别
底层不同:ArrayLIst和LInked: ArrayList底层是数组实现的,可以快速访问元素,而LinkedList需要从头或尾部进行遍历;对于删除元素时,LInkedList可以更快的删除元素,而ArrayLIst相对麻烦。针对不同情况进行选择;
适用场景不同: 对于频繁增删的使用LinkedLIst;对于随机访问和数据量较小的知识及顺序访问列表中的元素,使用ArrayList、 -
位运算
关于异或的规则:a^a =0, a^0 = a,;同时满足异或交换律,可以用于三次异或来进行交换两个数的值abc =acb -
Arrays中自带求和和排序方法:
使用Arrays内置的求和公式,Arrays.stream(inteferface{}).sum() 求和 ,Arrays.sort() 排序 但是相对时间复杂度会上升 -
栈
栈: 什么是栈? 先进后出,一种线性数据结构。
为什么链表可以用来表示栈 ??链表表示栈可以动态地添加和删除元素,更加灵活和强大,适合频繁的删除和添加元素场景。LInkedList和ArrayLIst都适合来表示栈,一般常用LinkedList来表示栈,ArrayList底层是一个数组,LinkedList底层是链表,更适合一些。同时链表中自带的方法,例如:addFirst,offerFirst,removeLast,pollLast方法组合可以很好的将元素push和pop进出栈。就时间复杂度而言,栈的入栈push和出栈pop操作都是O(1),同时使用两个栈来进行相互辅助,栈a作为存放元素,栈b作为存放非严格排序的元素,可以找到min值,就在栈b中 -
队列
什么是队列?先进先出,一种特殊的线性表
使用两个栈来实现队列的思路:两个栈S1和S2,一个用于插入元素(入队操作),一个用于删除元素(出队操作)
详细可针对具体题目具体分析~~
文章目录
- 杨辉三角
- 缺失数字
- 剑指Offer09.用两个栈实现队列
- 剑指Offer30. 包含min函数的栈
杨辉三角
class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> list = new ArrayList<>();
List<Integer> res = new ArrayList<>();
// 排除为0条件
if(numRows == 0) return list;
//将第一行添加到列表中
res.add(1);
list.add(res);
//从第二行开始进行遍历循环 i表示行数,j表示索引位置
for(int i =1;i<numRows;i++){
List<Integer> row = new ArrayList<>();
//首先在该行第一个位置加入1
row.add(1);
//因为 该行增添了一个1,该数向后挪动了一位,所以该数和为上一层的j和j+1组成
for(int j=0;j<list.get(i-1).size()-1;j++){
row.add(list.get(i-1).get(j)+list.get(i-1).get(j+1));
}
//在该行最后一位添上1,一位我的j的范围是取到倒数第二位
row.add(1);
list.add(row);
}
return list;
}
}
思路 && 学到的知识点:
- 首先是列表形式的选择,分别是ArrayList和LinkedList;
区别:ArrayList 底层是数组实现,利于快速访问元素,LinkedList需要从头或者尾部开始遍历,没有ArrayList方便,但是在删除元素时,LInkedList更方便;、
使用场景:对于频繁进行插入删除用lInkedList,对于随机访问,或者数据量较小的且只是顺序访问列表中的元素,使用ArrayList。 - 思路可以一步一步分析给出的代码,写的很清晰了步骤
缺失数字
代码:
// 位运算
public int missingNumber(int[] nums){
int xor =0;
for(int i=0;i<nums.length;i++){
xor ^= nums[i] ^i;
}
return xor^ nums.length;
}
//求和解法+
public int missingNumber(int[] nums){
int sum =0;
int length = nums.length;
int sum1=Arrays.stream(nums).sum();
for(int i =1;i<=length;i++){
sum +=i;
}
return sum-sum1;
}
学到的知识:
- 位运算操作:异或运算: 相同的数异或等于0;一个数和0异或为它自己;a ^ b ^ c = a ^ c ^b 具有交换律的性质
- 使用Arrays内置的求和公式,Arrays.stream(inteferface{}).sum() 求和
剑指Offer09.用两个栈实现队列
代码:
class CQueue {
LinkedList<Integer> A,B;
public CQueue() {
A = new LinkedList<Integer>();
B = new LinkedList<Integer>();
}
public void appendTail(int value) {
A.addLast(value);
}
public int deleteHead() {
if(!B.isEmpty()) return B.removeLast();
if(A.isEmpty()) return -1;
while(!A.isEmpty()){
B.addLast(A.removeLast());
}
return B.removeLast();
}
}
学到的知识:
- 栈: 什么是栈? 先进后出,一种线性数据结构。
为什么链表可以用来表示栈 ??链表表示栈可以动态地添加和删除元素,更加灵活和强大,适合频繁的删除和添加元素场景。LInkedList和ArrayLIst都适合来表示栈,一般常用LinkedList来表示栈,ArrayList底层是一个数组,LinkedList底层是链表,更适合一些。同时链表中自带的方法,例如:addFirst,offerFirst,removeLast,pollLast方法组合可以很好的将元素push和pop进出栈。 - 队列: 什么是队列?先进先出,一种特殊的线性表
使用两个栈来实现队列的思路:两个栈S1和S2,一个用于插入元素(入队操作),一个用于删除元素(出队操作)
流程: 在插入元素时,将元素push到s1栈中,在删除元素时,将s1中的所有元素都弹出来到s2中,然后将s2的栈顶元素出栈并返回,当s1和s2都为空时,则说明队列是空了
剑指Offer30. 包含min函数的栈
代码:
//难点:如何降低时间复杂度,因为 寻找最小元素 需要遍历整个栈,时间复杂度是O(n),
//因为普通栈的出栈和入栈的复杂度是 O(1),所以可以借助栈来进行降低时间复杂度
Stack<Integer> A,B;
public day6_13_4(){
A = new Stack<>();
B = new Stack<>();
}
public void push(int x){
A.add(x);
if(B.empty() || B.peek() >= x){
B.add(x);
}
}
public void pop(){
if (A.pop().equals(B.peek())){
B.pop();
}
}
public int top(){
return A.peek();
}
public int min(){
return B.peek();
}
学到的知识点:
- 就时间复杂度而言,栈的入栈push和出栈pop操作都是O(1),同时使用两个栈来进行相互辅助,栈a作为存放元素,栈b作为存放非严格排序的元素,可以筛选出。