文章目录

  • 算法
    • 前缀和
    • 双指针法
      • 四数之和
    • 分治算法
      • Offer 58 II 左旋转字符串
    • 回溯算法
    • 动态规划
  • 数据结构
    • 数组 & String & 双指针
    • 字符串
      • 反转字符串
      • T541 反转字符串II
      • 剑指 Offer 05. 替换空格
      • 字符串匹配——KMP的思路
    • 排序
      • 堆排序
    • DFS
    • 缓存方面
      • LRU
    • DFA 有穷自动机
      • 逆波兰表达式[未完成]
  • Java集合
    • JDK中Integer中的parseInt
    • Array 转成 List 或者 Set
      • Arrays.stream
    • DeQueue
    • Deque当作Stack
      • 用队列实现栈
    • Queue
      • 232. 用栈实现队列
    • 单调队列
    • PriorityQueue优先队列
    • Set
    • Map
      • 有效数独
  • 其他技巧
    • 把一个整数变成二进制数据
    • 数据类型导致的问题

算法

前缀和

Fig1

双指针法

这道题目15. 三数之和先对排序,然后在循环里面用双指针

四数之和

 public List<List<Integer>> fourSum(int[] nums, int target) {List<List<Integer>> result = new ArrayList<>();Arrays.sort(nums);for (int i = 0; i < nums.length; i++) {// 要加上这里的剪支操作if (nums[i] > target && (nums[i] >= 0 || target >= 0)) {break; // 这里使用break,统一通过最后的return返回}if (i > 0 && nums[i - 1] == nums[i]) {continue;}for (int j = i + 1; j < nums.length; j++) {// 2级剪枝处理if (nums[i] + nums[j] > target && (nums[i] + nums[j] >= 0 || target >= 0)) {break;}if (j > i + 1 && nums[j - 1] == nums[j]) {continue;}int left = j + 1;int right = nums.length - 1;while (right > left) {int sum = nums[i] + nums[j] + nums[left] + nums[right];if (sum > target) {right--;} else if (sum < target) {left++;} else {result.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));while (right > left && nums[right] == nums[right - 1]) right--;while (right > left && nums[left] == nums[left + 1]) left++;left++;right--;}}}}return result;}

分治算法

Offer 58 II 左旋转字符串

思路,分治的思路,把整体先选择一下,然后分部分选择;

 public String reverseLeftWords(String s, int n) {int len = s.length();StringBuilder str = new StringBuilder(s);if(n > len){n %= len;}reverse(str, 0, len-1);reverse(str, len-1-n+1, len-1);reverse(str, 0, len-1-n);return str.toString();}private void reverse(StringBuilder s, int start, int end){while(start <= end){char t = s.charAt(start);s.setCharAt(start, s.charAt(end));s.setCharAt(end, t);start++;end--;}}

回溯算法

回溯算法

动态规划

最长公共子序列
这种题目不要求连续,只要找出一个字符串 和 另一个字符串 最长的公共字符
https://zhuanlan.zhihu.com/p/311598413

数据结构

数组 & String & 双指针

双指针:删除字符串中的所有相邻重复项
String中常用的技巧双指针
String类API

  • equals和==
  • 常量池
  • internal();
//判断
boolean equals(Object obj)
boolean equalsIgnoreCase(String str)
boolean contains(String str)
boolean startsWith(String str)
boolean endsWith(String str)
boolean isEmpty()// 获取API
int length()
char charAt(int index)
int indexOf(int ch)
int indexOf(String str)
int indexOf(int ch,int fromIndex)
int indexOf(String str,int fromIndex)
String substring(int start)
String substring(int start,int end)// 转换
byte[] getBytes()
char[] toCharArray()
static String valueOf(char[] chs)
static String valueOf(int i)
String toLowerCase()
String toUpperCase()
String concat(String str)// 替换
替换功能
String replace(char old,char new)
String replace(String old,String new)
去除字符串两空格
String trim()
按字典顺序比较两个字符串
int compareTo(String str)
int compareToIgnoreCase(String str)

字符串

反转字符串

T541 反转字符串II

剑指 Offer 05. 替换空格

https://leetcode.cn/problems/ti-huan-kong-ge-lcof/
踩坑点,扩充字符只能append原来的2个,+原来的1个空格就是3个刚好’%20’

字符串匹配——KMP的思路

BF算法需要反复检验重复的字符
for i:=0 to j do
for j:= 0 to j do

KMP的重点:
- 关于失效数组的求法
- 根据失效数组进行回退

next 数组就是一个前缀表,用来回退
,记录了模式串和主串不匹配的时候,模式串应该从何处开始匹配
文本串 aabaabaafa
匹配串 aabaaf
当匹配串的指针指到f,文本串指针指向b,发现不等,此时,文本串指针不动,根据next回退匹配串

下标5之前这部分的字符串(也就是字符串aabaa)的最长相等的前缀 和 后缀字符串是 子字符串aa ,因为找到了最长相等的前缀和后缀,匹配失败的位置是后缀子串的后面,那么我们找到与其相同的前缀的后面从新匹配就可以了。

// 求next数组// kmp主体

排序

堆排序

https://www.cnblogs.com/chengxiao/p/6129630.html

最坏、好、平均时间复杂度O(nlong)
不稳定排序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tmWO2TJs-1666624361412)(evernotecid://684D322E-432A-47B1-9BC4-9F86BF974051/appyinxiangcom/17588966/ENResource/p1271)]

步骤一、构造初始堆

  • 从最后一个非叶子结点开始

DFS

void dfs()//参数用来表示状态
{  if(到达终点状态)  {  ...//根据题意添加  return;  }  if(越界或者是不合法状态)  return;  if(特殊状态)//剪枝return ;for(扩展方式)  {  if(扩展方式所达到状态合法)  {  修改操作;//根据题意来添加  标记;  dfs();  (还原标记);  //是否还原标记根据题意  //如果加上(还原标记)就是 回溯法  }  }
}

缓存方面

LRU

https://leetcode.cn/problems/lru-cache/


class LRUCache {private static class MyLinkedNode{public int key;public int val;public MyLinkedNode prev;public MyLinkedNode next;public MyLinkedNode(){}public MyLinkedNode(int key, int val){this.key = key;this.val = val;}}private MyLinkedNode dummyHead = new MyLinkedNode();private MyLinkedNode dummyTail = new MyLinkedNode();private Map<Integer, MyLinkedNode> map = new HashMap<>();private int capacity = 0;public LRUCache(int capacity) {this.capacity = capacity;dummyHead.next = dummyTail;dummyTail.prev = dummyHead;}public int get(int key) {if(!map.containsKey(key)){return -1;}MyLinkedNode node = map.get(key);moveToFirst(node);return node.val;}public void put(int key, int value) {MyLinkedNode node;if(map.containsKey(key)){node = map.get(key);node.val = value;moveToFirst(node);}else{node = new MyLinkedNode(key,value);map.put(key, node);insertFirst(node);if(map.size() > capacity){// 移除最后一个node = removeTail();map.remove(node.key);}} }private void deleteNode(MyLinkedNode node){node.prev.next = node.next;node.next.prev = node.prev;node.prev = null;node.next = null;}private void insertFirst(MyLinkedNode node){node.prev = dummyHead;node.next = dummyHead.next;dummyHead.next.prev = node;dummyHead.next = node;}private void moveToFirst(MyLinkedNode node){deleteNode(node);insertFirst(node);}private MyLinkedNode removeTail(){MyLinkedNode node = dummyTail.prev;deleteNode(node);return node;}
}/*** Your LRUCache object will be instantiated and called as such:* LRUCache obj = new LRUCache(capacity);* int param_1 = obj.get(key);* obj.put(key,value);*/

DFA 有穷自动机

//实现DFA
class Automaton{public int sign = 1;public long ans = 0;private String state = "start"; //起始态Map<String, String[]> map = new HashMap<>(){{  //构建一个状态转移表put("start", new String[]{"start", "signed", "in_number", "end"});put("signed", new String[]{"end", "end", "in_number", "end"});put("in_number", new String[]{"end", "end", "in_number", "end"});put("end", new String[]{"end", "end", "end", "end"});}};public void get(char c){state = map.get(state)[get_ele(c)];if("in_number".equals(state)){ans = ans * 10 + c - '0';ans = sign == 1? Math.min(ans,(long) Integer.MAX_VALUE):Math.max(ans, -(long)Integer.MIN_VALUE);}else if("sign".equals(state)){sign = sign == '+'?1:-1;}}private int get_ele(char c){if(c == ' '){return 0;}if(c == '+' || c == '-'){return 1;}if(Character.isDigit(c)){return 2;}return 3;}
}

逆波兰表达式[未完成]

后缀表达式,波兰罗辑学家1929年提出的一种表达是的表示方法。把运算量写在前面,把运算符写在后面。

    1. 表达式计算
      4https://www.acwing.com/problem/content/153/

Java集合

JDK中Integer中的parseInt

int limit = -Integer.MAX_VALUE;
int multmin = limit / radix;
int result = 0;
while (i < len) {// Accumulating negatively avoids surprises near MAX_VALUEint digit = Character.digit(s.charAt(i++), radix);if (digit < 0 || result < multmin) {throw NumberFormatException.forInputString(s);}result *= radix;if (result < limit + digit) {throw NumberFormatException.forInputString(s);}result -= digit;
}
return negative ? result : -result;

Array 转成 List 或者 Set

List list = Arrays.asList(数组);
Set<数据类型> set = new HashSet<>(Arrays.asList(数组));
// List 转成 Set
Set<数据类型> set = new HashSet<>(list);
数据类型[] arr = list.toArray(new 数据类型(list.size()));
// Set 转 list
List<数据类型> list = new ArrayList<>(set);Object[] toArray();
<T> T[] toArray(T[] a);List<String> strList = new ArrayList<>();
strList.add("list-a");
strList.add("list-b");
String[] strArray = strList.toArray(new String[strList.size()]);Arrays.asList(“a”,”b”,”c”); //Arrays.asList(T… a)Arrays.stream(digits);    //会把数组编程steamStream.of(digits);        //return streamList<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");//size=7List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());//size=5 把""过滤掉了
System.out.println("筛选列表: " + filtered);//筛选列表: [abc, bc, efg, abcd, jkl]String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("合并字符串: " + mergedString);//合并字符串: abc, bc, efg, abcd, jkl

Arrays.stream

Stream<String> stream = Arrays.stream(arr);
// Displaying elements in Stream
stream.forEach(str -> System.out.print(str + " "));

DeQueue

Deque的API:Deque是一个双端队列

Deque的使用场景,不涉及到并发操作,有两个实现类、

  • LinkedList 大小可变的链表双端队列,允许元素为插入null。
  • ArrayDeque 大下可变的数组双端队列,不允许插入null。
  • ConcurrentLinkedDeque 大小可变且线程安全的链表双端队列,非阻塞,不允许插入null。
  • LinkedBlockingDeque 为线程安全的双端队列,在队列为空的情况下,获取操作将会阻塞,直到有元素添加。

Deque当作Stack

2. private Deque<Integer> data = new ArrayDeque<Integer>();   public void push(Integer element) {   data.addFirst(element);   }   public Integer pop() {   return data.removeFirst();   }   public Integer peek() {   return data.peekFirst();   }   可以直接用
Deque<Character> stack = new LinkedList<>();
stack.peek();
stack.push();
stack.pop();

用队列实现栈

队列实现栈的思路

q1 作为主要的栈,q2 作为辅助栈,每次push 操作先放到q2中,在把q1的数据出队放到q2,然后交换q1、q2
class MyStack {Deque<Integer> q1 = new LinkedList<>();Deque<Integer> q2 = new LinkedList<>();public MyStack() {}public void push(int x) {q2.offer(x);while(!q1.isEmpty()){q2.offer(q1.poll());}Deque<Integer> t = q1;q1 = q2;q2 = t;}public int pop() {return q1.poll();}public int top() {return q1.peek();}public boolean empty() {return q1.isEmpty();}
}

Queue

232. 用栈实现队列

class MyQueue {Deque<Integer> s1 = new LinkedList<>();Deque<Integer> s2 = new LinkedList<>();public MyQueue() {}public void push(int x) {s1.push(x);}public int pop() {dumpstackIn();return s2.pop();}public int peek() {   dumpstackIn();return s2.peek();}private void dumpstackIn(){if(s2.isEmpty())while(!s1.isEmpty()){s2.push(s1.pop());}return ;}public boolean empty() {return s1.isEmpty() && s2.isEmpty();}
}

单调队列

https://leetcode.cn/problems/sliding-window-maximum/

这个题目只需要维护一个单调减队列,让队头始终保持最大元素。

PriorityQueue优先队列

二叉堆:有序的完全二叉排序树,
中间节点k/2,左儿子2k,右儿子2k+1
堆的插入

  • 放在堆尾,然后调整,上浮到何时位置

堆的删除

  • 我们从数组顶端删去最大的元素并将数组的最后一个元素放到顶端,减小堆的大小并让这个元素下沉到合适的位置

Set

// 常用方法
add(Object obj);
Interator iterator = set.iterator();
while(iterator.hasNext()){iterator.next();
}
// 边迭代边修改的问题
// solution,使用iterator// foreach中,会使用.next() 在删除元素之后被调用 ConcurrentModificationException

HashSet与LinedHashSet

  • HashSet
  • LinkedHashSet,有序,插入性能没有HashSet好,但是迭代访问要好
  • TreeSet:不能写入null、写入的数据是有序的。所以有序 + 去重复就用这

TreeSet底层是红黑树

Map

遍历Map的用法

for (Map.Entry<Integer, Integer> entry : counts.entrySet()) {if (majorityEntry == null || entry.getValue() > majorityEntry.getValue()) {majorityEntry = entry;}
}

有效数独

判断行、列没有重复的1-9,以及一个小的3 * 3数字没有重复的1-9
这道题目,人家用hash做的解法比自己简单不少,在求小方格的时候,并没有直接去做,而是用计算关系去弄,很精彩。

class Solution {public boolean isValidSudoku(char[][] board) {Map<Integer, Set<Integer>> row  = new HashMap<>(), col = new HashMap<>(), area = new HashMap<>();for (int i = 0; i < 9; i++) {row.put(i, new HashSet<>());col.put(i, new HashSet<>());area.put(i, new HashSet<>());}for (int i = 0; i < 9; i++) {for (int j = 0; j < 9; j++) {char c = board[i][j];if (c == '.') continue;int u = c - '0';int idx = i / 3 * 3 + j / 3;if (row.get(i).contains(u) || col.get(j).contains(u) || area.get(idx).contains(u)) return false;row.get(i).add(u);col.get(j).add(u);area.get(idx).add(u);}}return true;}
}作者:AC_OIer
链接:https://leetcode.cn/problems/valid-sudoku/solution/gong-shui-san-xie-yi-ti-san-jie-ha-xi-bi-ssxp/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

其他技巧

把一个整数变成二进制数据

// 计算给定的整数的二进制表示中的 1 的数目
Integer.bitCount
public static int bitCount(int i) {// HD, Figure 5-2i = i - ((i >>> 1) & 0x55555555);i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);i = (i + (i >>> 4)) & 0x0f0f0f0f;i = i + (i >>> 8);i = i + (i >>> 16);return i & 0x3f;
}// 2 Brain Kernighan算法
// 对于任意整数 x,令 x=x & (x−1),该运算将 x 的二进制表示的最后一个 1 变成 0
int cnt = 0;
while(x != 0){x &= (x-1);cnt++;
}// 3 动态规划 最高有效位
int[] dp = new int[n+1];
dp[0] = 0;
dp[1] = 1;
for(int i = 2; i <= n; i++){// 寻找 j<=x && j/2==0if(i & (i-1) == 0){y = i;dp[i] = dp[0] + 1;}else{y = i-1;dp[i] = dp[y] + 1;}
}// 4 动态规划 最低有效位
bit[x] = bit[x>>1] + (x&1);// 5 动态规划—最低设置位
bits[x] = bits[x & (x-1)] + 1;

数据类型导致的问题

数据需要mod,考虑用long数据类型:https://leetcode.cn/problems/prime-arrangements/(1175、质数排列)

【算法和数据结构学习笔记】整合版相关推荐

  1. 谈谈算法(数据结构学习笔记)

    文章目录 什么是算法 算法举例 高斯简算1到100加法 算法的五个基本特征 算法设计的要求 什么是算法 算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作 ...

  2. 【C++算法与数据结构学习笔记------用循环数组实现队列】

    照王晓东<数据结构>(C++语言版)上打的,以备留用. 1 #include <iostream> 2 using namespace std; 3 template<t ...

  3. 尚硅谷算法与数据结构学习笔记05 -- 递归

    1.递归介绍 1.1.递归应用场景 看个实际应用场景, 迷宫问题(回溯), 递归(Recursion) 1.2.递归的概念 简单的说: 递归就是方法自己调用自己,每次调用时传入不同的变量,递归有助于编 ...

  4. 数据结构学习笔记——顺序表的基本操作(超详细最终版+++)建议反复看看ヾ(≧▽≦*)o

    目录 前言 一.顺序表的定义 二.顺序表的初始化 三.顺序表的建立 四.顺序表的输出 五.顺序表的逆序输出 六.顺序表的插入操作 七.顺序表的删除操作 八.顺序表的按位和按值查找 基本操作的完整代码 ...

  5. 《算法图解》学习笔记(十一):十种经典的算法与数据结构

    python学习之路 - 从入门到精通到大师 文章目录 [python学习之路 - 从入门到精通到大师](https://blog.csdn.net/TeFuirnever/article/detai ...

  6. Python数据结构学习笔记——队列和双端队列

    目录 一.队列的定义 二.队列 实现步骤分析 三.队列的Python实现代码 四.队列的应用 六人传土豆游戏 五.双端队列的定义 六.双端队列 实现步骤分析 七.双端队列的Python实现代码 八.双 ...

  7. 考研[*数据结构*]学习笔记汇总(全)

    文章目录: 一:预备阶段 二:基础阶段笔记 三:冲刺阶段笔记 四:各章节思维导图 五:题库 来源:王道计算机考研 数据结构 一:预备阶段 之前的数据结构笔记 数据结构--学习笔记--入门必看[建议收藏 ...

  8. Python数据结构学习笔记——链表:无序链表和有序链表

    目录 一.链表 二.无序链表 实现步骤分析 三.无序链表的Python实现代码 四.有序链表 实现步骤分析 五.有序链表的Python实现代码 结语 一.链表 链表中每一个元素都由为两部分构成:一是该 ...

  9. Python数据结构学习笔记——栈

    目录 一.栈的定义和特性 (一)栈的定义 (二)栈的反转特性 二.实现分析步骤 三.栈的Python实现代码 四.栈的应用 (一)匹配圆括号 (二)匹配符号 (三)模2除法(十进制转二进制) (四)进 ...

最新文章

  1. Uber无人车撞人视频公布,究竟哪儿出问题了?
  2. 31.return和call的区别
  3. MATLAB显示错误使用untitled,使用Matlab 2016a阻止集合构建错误
  4. 程序员:代码全部替换成中文,你能接受吗?
  5. 对于数据,科技小白提出了灵魂三问:从哪儿来?到哪儿去?能干什么?
  6. 从零开始学前端:过渡和动画 --- 今天你学习了吗?(CSS:Day20)
  7. 利用rman配置DG环境
  8. 吉林大学java期末试卷_吉大18年9月《JAVA程序设计》作业考核试题-0001
  9. 刘世锦:引入区块链等相关技术建立政府、企业和个人的绿色责任账户
  10. vfp 修改本机时间_借助novapdfPro 将VFP报表无感生成PDF文件
  11. faster rcnn fpn_Faster-RCNN详解和torchvision源码解读(三):特征提取
  12. mac 电脑 打开隐藏文件
  13. Abode Photoshop CC 2019之更换图片颜色
  14. 知道创宇爬虫题--代码持续更新中
  15. python随机数种子seed()的讲解
  16. 计算机组成原理是答案,计算机组成原理(上)_答案mooc
  17. 此身, 此时, 此地
  18. 百度前端技术学院--零基础--第四天:背景边框列表链接和更复杂的选择器
  19. linux下LPC访问CPLD
  20. uname -r和uname -a

热门文章

  1. 索尼IMX316 标定_ToF模块相机校准
  2. docker 安装的软件所在的目录及配置
  3. 数据结构与算法05----图
  4. Simulink Simscape基础仿真电路
  5. 某大型展会现场病毒排查事例及安全规划建议
  6. linux申请端口,linux申请端口申请书
  7. SpringBoot整合knife和swagger3
  8. 每天干的啥?(2018.02)
  9. 巧用Word目录和标题
  10. asp.net 页面加载