递归复杂度求解
数组求和的递归实现
package cn.algorithm;
public class Numsum {
//递归实现数组求和
public static void main(String[] args) {
int arr[] = {1,4,3,2,4};
int res= msum(arr,0,arr.length-1);
System.out.println(res);
}
public static int msum(int arr[],int L, int R){
if (L==R){
return arr[L];
}
int mid = (L+R)/2;
return msum(arr,L,mid)+msum(arr,mid+1,R);
}
}
归并排序
归并排序实现
package cn.algorithm;
public class MergeSort {
public static void main(String[] args) {
int arr[] = {4,2,8,9,3,4,2,1};
sortProcess(arr,0,arr.length-1);
for (int x:
arr) {
System.out.printf(x+" ");
}
}
public static void sortProcess(int arr[],int L,int R){
if (L==R)
return;
int mid = L + ((R-L)>>1);
sortProcess(arr,L,mid); //递归
sortProcess(arr,mid+1,R);
merge(arr,L,mid,R); //进行一次归并排序
}
public static void merge(int arr[],int L, int mid, int R){
int [] help = new int[R-L+1];
int i = 0;
int p = L;
int q = mid+1;
while (p<=mid && q<=R){
help[i++] = arr[p] < arr[q] ? arr[p++] : arr[q++]; //比较大小,填充
}
while (p<=mid){
help[i++] = arr[p++];
}
while(q<=R){
help[i++] = arr[q++];
}
for (i=0;i<help.length;i++){
arr[L+i] = help[i]; //将每次排序好的数据复制给原数组
}
}
}
小和问题
在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和,求一个数组的小和
此处使用归并排序,在 merge 时,由于左右两部分都已经有序,可以确定一侧的数都大于正在比较的数,例如:
归并 2 4 5 | 1 3 7 两个部分时,2 比 3 小,此时可以确定后面的数都大于 2,此时便可以一次性计算小和 2 * 2(两个数大于 2),而不用一个个遍历。
package cn.algorithm;
public class smallSum {
public static void main(String[] args) {
int arr[] = {4,2,8,9,3,4,2,1};
int res = sortProcess(arr,0,arr.length-1);
System.out.println(res);
}
public static int sortProcess(int arr[],int L,int R){
if (L==R)
return 0;
int mid = L + ((R-L)>>1); //防止溢出,位操作,>> 1 除2
return sortProcess(arr,L,mid) +sortProcess(arr,mid+1,R) + merge(arr,L,mid,R);
}
public static int merge(int arr[],int L, int mid, int R){
int [] help = new int[R-L+1];
int i = 0;
int p = L;
int q = mid+1;
int res = 0;
while (p<=mid && q<=R){
res += arr[p] < arr[q] ? (R - q + 1)*arr[p] : 0; //计算每个数的小和
help[i++] = arr[p] < arr[q] ? arr[p++] : arr[q++];
}
while (p<=mid){
help[i++] = arr[p++];
}
while(q<=R){
help[i++] = arr[q++];
}
for (i=0;i<help.length;i++){
arr[L+i] = help[i];
}
return res;
}
}
逆序对问题
在一个数组中,左边的数如果比右边的数大,则折成两个数构成逆序对,请打印所有逆序个数。(和小和问题一样解决)
package cn.algorithm;
public class InverseSort {
public static void main(String[] args) {
int num [] = {1,5,3,6};
int res = sortProcess(num,0,num.length-1);
System.out.println(res);
}
public static int sortProcess(int arr[],int L,int R){
if (L==R)
return 0;
int mid = L + ((R-L)>>1);
return sortProcess(arr,L,mid) +sortProcess(arr,mid+1,R) + merge(arr,L,mid,R);
}
public static int merge(int arr[],int L, int mid, int R){
int [] help = new int[R-L+1];
int i = 0;
int p = L;
int q = mid+1;
int res = 0;
while (p<=mid && q<=R){
res += arr[p] > arr[q] ? (R - q + 1) : 0;
help[i++] = arr[p] > arr[q] ? arr[p++] : arr[q++];
}
while (p<=mid){
help[i++] = arr[p++];
}
while(q<=R){
help[i++] = arr[q++];
}
for (i=0;i<help.length;i++){
arr[L+i] = help[i];
}
return res;
}
}
快速排序
荷兰国旗问题:
给定一个数组arr,和一个数num,请把小于num的数放在左边,大于num的数放在右边,等于num的数放在中间
要求时间复杂度为O(N),空间复杂度为O(1)
package cn.algorithm;
public class NeitherlandsFlg {
public static void main(String[] args) {
int arr[]= {5,4,3,5,9,1,5,6,7,2};
partition(arr,0,arr.length-1,5);
for (int i:
arr) {
System.out.printf(i+" ");
}
}
public static void partition(int arr[],int L, int R, int num){
int left = L-1;
int more = R+1;
while (L< more){
if (arr[L] < num){
swap(arr,L++,++left);
}
else if (arr[L] > num){
swap(arr,L,--more);
}
else {
L++;
}
}
}
public static void swap(int arr[], int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
快速排序实现
时间复杂度O(N*logN),最差O(N^2),空间复杂度O(logN)
package cn.algorithm;
//递归实现
public class QuickSort {
public static void main(String[] args) {
int nums[] = {3,9,1,5,2,7,5,10,0};
QuickSort quickSort = new QuickSort();
quickSort.quickSort(nums);
for (int num:nums
) {
System.out.printf(num+" ");
}
}
public void quickSort(int nums[]){
if(nums == null || nums.length==0)return;
qSort(nums,0,nums.length-1);
}
public void qSort(int nums[],int low,int high){
if(low>=high)return;
while (low<high){
int privot = partition(nums,low,high);
qSort(nums,0,privot-1);
low = privot+1;
}
}
public int partition(int nums[],int low,int high){
int privotValue = nums[low];
while (low<high){
while (low<high && nums[high]>=privotValue)high--;
swap(nums,low,high);
while (low<high && nums[low]<=privotValue)low++;
swap(nums,low,high);
}
return low;
}
public void swap(int nums[],int i,int j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
package cn.algorithm;
import java.util.Stack;
//非递归实现
public class QuickSort2 {
public static void main(String[] args) {
int nums[] = {3,6,1,8,3,9,2,7,4,0};
QuickSort quickSort = new QuickSort();
quickSort.quickSort(nums);
for (int num:nums
) {
System.out.printf(num+" ");
}
}
void quickSort(int nums[]){
if(nums==null || nums.length==0)return;
qSort(nums,0,nums.length-1);
}
void qSort(int nums[],int low,int high){
if(low>=high)return;
Stack<Integer> stack = new Stack<>();
stack.push(low);
stack.push(high);
while(low<high){
high = stack.pop();
low = stack.pop();
int privot = partition(nums,low,high);
stack.push(low);
stack.push(privot-1);
stack.push(privot+1);
stack.push(high);
}
}
int partition(int nums[],int low,int high){
int privot = nums[low];
while(low<high){
while (low<high && nums[high]>=privot)high--;
swap(nums,low,high);
while (low<high && nums[low]<=privot)low++;
swap(nums,low,high);
}
return low;
}
void swap(int nums[],int i,int j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = nums[i];
}
}
堆排序
时间复杂度O(N*logN) ,额外空间复杂度O(1)
package cn.algorithm;
public class Heapsort {
public static void main(String[] args) {
int arr[]= {5,4,3,5,9,1,5,6,7,2};
heapsort(arr);
for (int num:
arr) {
System.out.printf(num + " ");
}
}
public static void heapsort(int arr[]){
if (arr == null || arr.length<2)
return;
// 建立大根堆
for (int i=0;i<arr.length;i++){
heapinsert(arr,i);
}
//堆排序
int heapsize = arr.length;
swap(arr,0,--heapsize);
while (heapsize>0){
heapify(arr,0,heapsize);
swap(arr,0,--heapsize);
}
}
//建立大根堆
public static void heapinsert(int arr[], int index){
while (arr[index] > arr[(index-1)/2]){
swap(arr,index,(index-1)/2);
index = (index-1)/2;
}
}
// 排最大值
public static void heapify(int arr[],int index, int heapsize){
int left = index*2 + 1;
while (left<heapsize){
int largest = (left+1) < heapsize && arr[left+1] > arr[left] ? left+1 : left;
largest = arr[largest] > arr[index] ? largest : index;
if (largest == index)
break;
swap(arr,largest,index);
index = largest;
left = largest*2+1;
}
}
public static void swap(int arr[], int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
相邻最大差值:
给定一个数组,求如果排序之后,相邻两个数的最大差值,要求时间复杂度为O(N),且要求不能用非基于比较的的排序。
package cn.algorithm;
/*
1.找出最大值,最小值
2.定义N+1个桶,每个桶有最大值 最小值 与有无数据布尔值
3.每个数插入对应桶 并更新最大值 最小值 与有无数据布尔值
4.非空桶最小值减去最近前非空桶最大值
即为排序后的最大值
*/
public class MaxDiffer {
public static void main(String[] args) {
int arr[] = {4,2,8,9,3,4,2,1};
int res = maxdiff(arr);
System.out.println(res);
}
public static int maxdiff(int []arr){
if (arr==null || arr.length<2)
return 0;
int len = arr.length;
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for (int i=0;i<len;i++){
min = Math.min(min,arr[i]);
max = Math.max(max,arr[i]);
}
if (min==max)
return 0;
boolean []hasnum = new boolean[len+1];
int [] mins = new int[len+1];
int [] maxs = new int[len+1];
int bid = 0;
for (int i=0;i<len;i++){
bid = buket(arr[i],len,min,max);
mins[bid] = hasnum[bid] ? Math.min(arr[i],mins[bid]) : arr[i];
maxs[bid] = hasnum[bid] ? Math.max(arr[i],maxs[bid]) : arr[i];
hasnum[bid] = true;
}
int res = 0;
int lastmax = maxs[0];
int i=1;
for (;i<=len;i++){
if (hasnum[i]){
res = Math.max(res,mins[i]-lastmax);
lastmax = maxs[i];
}
}
return res;
}
public static int buket(int num,int len,int min,int max){
return (int)((num-min)*len/(max-min));
}
}
用数组结构实现大小固定的栈和队列
package cn.structure;
import org.w3c.dom.css.CSSImportRule;
public class stackqueue {
public static void main(String[] args) {
Arraystack arraystack = new Arraystack(5);
arraystack.push(5);
System.out.println(arraystack.pop());
}
}
class Arraystack{
private Integer[] arr;
private Integer index;
public Arraystack(int initsize){
if (initsize<0){
throw new IllegalArgumentException("The init siza is less than 0");
}
arr = new Integer[initsize];
index = 0;
}
public Integer peek(){
if (index==0) {
return null;
}
return arr[index-1];
}
public void push(int obj){
if (index==arr.length){
throw new ArrayIndexOutOfBoundsException("The stack is full");
}
arr[index++] = obj;
}
public Integer pop(){
if (index ==0 ){
throw new ArrayIndexOutOfBoundsException("The stack is empty");
}
return arr[--index];
}
}
class ArrayQueue{
private Integer [] arr;
private Integer start;
private Integer end;
private Integer size;
public ArrayQueue(int initsize){
if (initsize<0){
throw new IllegalArgumentException("The init size is less than 0");
}
arr = new Integer[initsize];
start = 0;
end = 0;
size = 0;
}
public Integer peek(){
if (size==0){
throw new ArrayIndexOutOfBoundsException("The stack is empty");
}
return arr[start];
}
public void push(Integer obj){
if (size == arr.length){
throw new ArrayIndexOutOfBoundsException("The queue is full")
}
arr[end] = obj;
end = nextindex(arr.length,end);
size++;
}
public Integer poll(){
if (size==0){
throw new ArrayIndexOutOfBoundsException("The stack is empty");
}
size--;
int tmp = start;
start = nextindex(arr.length,start);
return arr[tmp];
}
public Integer nextindex(int size, int index){
return index==size-1 ? 0:index+1;
}
}
实现一个特殊的栈,要求实现栈的基本功能的基础上,再能实现返回栈中最小的元素。
要求:
pop,push,getMin操作的时间复杂度可以是O(1).
可以使用现成的栈类型结构
package cn.structure;
/*
1、建立一个最小值栈
2、stackData加数据和出数据时,保持stackMin同步压入 压出,(压入value比stackMin小,直接压入stackMin,比stackMin大,压入stackMin和stackMin当前相同最小值)
3.stackData,stackMin同时pop
*/
import java.util.Stack;
public class minstack {
private Stack<Integer> stackData;
private Stack<Integer> stackMin;
public minstack(){
stackData = new Stack<Integer>();
stackMin = new Stack<Integer>();
}
public void push(int obj){
if (this.stackMin.isEmpty()){
this.stackMin.push(obj);
}else if (obj < this.stackMin.peek()){
this.stackMin.push(obj);
}else {
int getmin = this.stackMin.peek();
this.stackMin.push(getmin);
}
this.stackData.push(obj);
}
public int pop(){
if (this.stackData.isEmpty()){
throw new RuntimeException("the stackdata is empty");
}
this.stackMin.pop();
return this.stackData.pop();
}
public int getMin(){
if (this.stackMin.isEmpty()){
throw new RuntimeException("this stackmin is empty");
}
return this.stackMin.peek();
}
}
package cn.structure;
import java.util.Stack;
/*
1、建立一个最小值栈
2、stackData加数据和出数据时,保持stackMin同步压入 压出,(压入value比stackMin小,直接压入stackMin,比stackMin大,压入stackMin和stackMin当前相同最小值)
3.stackData,stackMin同时pop
)下面简化版本
压入value比stackMin当前大,就不压入,节省空间
*/
public class minstack {
private Stack<Integer> stackData;
private Stack<Integer> stackMin;
public minstack(){
stackData = new Stack<Integer>();
stackMin = new Stack<Integer>();
}
public void push(int obj){
if (this.stackMin.isEmpty()){
this.stackMin.push(obj);
}
else if (obj < this.stackMin.peek()){
this.stackMin.push(obj);
}
this.stackData.push(obj);
}
public int pop(){
if (this.stackData.isEmpty()){
throw new RuntimeException("the stackdata is empty");
}
if (this.stackMin.peek()==this.stackData.peek()){
this.stackMin.pop();
}
return this.stackData.pop();
}
public int getMin(){
if (this.stackMin.isEmpty()){
throw new RuntimeException("this stackmin is empty");
}
return this.stackMin.peek();
}
}
如何仅使用栈结构实现队列
如何仅使用队列结构实现栈(应用:使用队列实现图的深度优先遍历)
package cn.structure;
import java.util.LinkedList;
import java.util.Queue;
/*
两个队列实现栈结构
*/
public class twoqueuestack {
private Queue<Integer> queue;
private Queue<Integer> help;
public twoqueuestack(){
queue = new LinkedList<Integer>();
help = new LinkedList<Integer>();
}
public void push(int obj){
queue.add(obj);
}
public int peek(){
if (queue.isEmpty()){
throw new RuntimeException("the queue is empty");
}
while (queue.size()>1){
help.add(queue.poll());
}
int res = queue.poll();
help.add(res);
swap();
return res;
}
public int poll(){
if (queue.isEmpty()){
throw new RuntimeException("the queue is empty");
}
while (queue.size()>1){
help.add(queue.poll());
}
int res = queue.poll();
swap();
return res;
}
public void swap(){
Queue<Integer> tmp = queue;
queue = help;
help = queue;
}
}
package cn.structure;
import java.util.Stack;
/*
两原则:
1.stackPop为空时,stackPush栈才能往stackPop导数据
2.stackPush往stackPop导数据,导全部数据
*/
public class twostackqueue {
private Stack<Integer> stackPush;
private Stack<Integer> stackPop;
public twostackqueue(){
stackPop = new Stack<Integer>();
stackPush = new Stack<Integer>();
}
public void push(int obj){
stackPush.push(obj);
}
public int poll(){
if (stackPop.isEmpty()&&stackPush.isEmpty()){
throw new RuntimeException("the queue is empty");
}
if (stackPop.isEmpty()){
while (!stackPush.isEmpty()){
stackPop.push(stackPush.pop());
}
}
int res = stackPop.pop();
return res;
}
public int peek(){
if (stackPush.empty() && stackPop.empty()){
throw new RuntimeException("the queue is empty");
}
return stackPop.peek();
}
}
队列的最大值
请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。
若队列为空,pop_front 和 max_value 需要返回 -1
class MaxQueue {
Queue<Integer> q;
Deque<Integer> d;
public MaxQueue() {
q = new LinkedList<>();
d = new LinkedList<>();
}
public int max_value() {
if(q.isEmpty()){
return -1;
}
return d.peekFirst();
}
//和滑动窗口类似
public void push_back(int value) {
while(!d.isEmpty() && d.peekLast()<value){
d.pollLast();
}
d.addLast(value);
q.add(value);
}
public int pop_front() {
if(q.isEmpty()){
return -1;
}
int ans = q.poll();
if(ans == d.peekFirst()){
d.pollFirst();
}
return ans;
}
}
哈希表
package cn.structure;
import java.util.HashMap;
/*
题目:
设计一种结构,在该结构中有如下三种功能
insert(key):将某个key 加入该结构中,做到不重复加入
delete(key): 将原本在结构中得某个key移除
getRandom():等概率得返回结构中得任何一个key
要求:
insert,delete,getRandom方法的时间复杂度为O(1)
*/
public class RandomPool {
private HashMap<String,Integer> map1 = new HashMap<>();
private HashMap<Integer,String> map2 = new HashMap<>();
private int size=0;
public void insert(String str){
if (!map1.containsKey(str)){
map1.put(str,size);
map2.put(size++,str);
}
}
public void delete(String str){
if (map1.containsKey(str)){
int delindex = map1.get(str);
int lastindex = map1.size()-1;
String ss = map2.get(lastindex);
map1.put(ss,delindex);
map2.put(delindex,ss);
map1.remove(str);
map2.remove(lastindex);
size--;
}
}
public String getRandom(){
int num = map1.size();
if (num==0){
return null;
}
return map2.get((int)(Math.random()*size));
}
}
链表
public class LinkList {
//添加节点
public void insertList(ListNode head, int value){
ListNode listNode = new ListNode(value);
if (head == null){
head = listNode;
}else {
ListNode p = head;
while (p.next!=null){
p = p.next;
}
p.next = listNode;
}
}
//删除节点
public void deleteList(ListNode head, int value){
if (head==null)return;
if (head.val == value){
head = head.next;
}else {
ListNode p = head;
while (p.next != null && p.val != value){
p = p.next;
}
if (p.next!=null) {
p.next = p.next.next;
}
}
}
//从尾到头打印链表
public void printList(ListNode head){
Stack<ListNode> stack = new Stack<>();
ListNode p = head;
while (p!=null){
stack.push(p);
p = p.next;
}
while (!stack.isEmpty()){
p = stack.pop();
System.out.printf(p.val+" ");
}
}
//反转链表
public void reverseList(ListNode head){
ListNode newhead = null;
ListNode node;
while (head!=null){
//先做头删
node = head;
head =head.next;
//新链表做头插
node.next = newhead;
newhead= node;
}
}
}
二叉树
class BinaryTreeNode{
int val;
BinaryTreeNode left;
BinaryTreeNode right;
public BinaryTreeNode(int val){
this.val = val;
}
}
public class BinaryTree {
//前序 递归
public void preOrderRec(BinaryTreeNode head){
if (head==null){
return;
}
System.out.printf(head.val+" ");
preOrderRec(head.left);
preOrderRec(head.right);
}
//中序 递归
public void inOrderRec(BinaryTreeNode head){
if (head==null){
return;
}
inOrderRec(head.left);
System.out.printf(head.val+" ");
inOrderRec(head.right);
}
//后序 递归
public void posOrderRec(BinaryTreeNode head){
if (head==null){return;}
posOrderRec(head.left);
posOrderRec(head.right);
System.out.printf(head.val+" ");
}
public void preOrderUn(BinaryTreeNode head){
if (head == null){
return;
}
Stack<BinaryTreeNode> stack = new Stack<>();
stack.push(head);
while (!stack.isEmpty()){
head = stack.pop();
System.out.printf(head.val+" ");
if (head.right!=null){
stack.push(head.right);
}
if (head.left!=null){
stack.push(head.left);
}
}
}
// 中序 非递归
//
public void inOrderUn(BinaryTreeNode head){
if (head == null){
return;
}
Stack<BinaryTreeNode> stack = new Stack<>();
while (!stack.isEmpty() || head!=null){
if (head!=null){
stack.push(head);
head = head.left;
}else {
head = stack.pop();
System.out.printf(head.val+" ");
head = head.right;
}
}
}
//非递归 后序
// 1) 弹,固定cur
// 2) cur放入收栈
// 3)先压左节点,再压右节点
public void posOrderUn(BinaryTreeNode head){
if (head==null){
return;
}
Stack<BinaryTreeNode> stack1 = new Stack<>();
Stack<BinaryTreeNode> stack2 = new Stack<>();
stack1.push(head);
while (!stack1.isEmpty()){
head = stack1.pop();
stack2.push(head);
if (head.left!=null){
stack1.push(head.left);
}
if (head.right!=null){
stack1.push(head.right);
}
}
while (!stack2.isEmpty()){
head = stack2.pop();
System.out.printf(head.val+" ");
}
}
}
平衡二叉树
/*输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
*/
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isBalanced(TreeNode root) {
if(root==null)return true;
return Math.abs(depth(root.left)-depth(root.right))<=1 && isBalanced(root.left) && isBalanced(root.right);
}
public int depth(TreeNode root){
if(root==null)return 0;
return Math.max(depth(root.left),depth(root.right))+1;
}
}
Double类型不能用==判断是否相等
boolean Equal(double num1, double num2){
if((num1-num2 >-0.0000001) && (num1-num2 < 0.0000001)){
return true;
}
else{
return false;
}
}
字符全部子序列
子序列可以删除元素也可以不删除元素,但顺序不变
package alorithm;
import java.util.ArrayList;
import java.util.List;
public class StringProcess {
public List<String> subs(String s){
char[] str = s.toCharArray();
String path = "";
List<String> ans = new ArrayList<>();
process(str,0,ans,path);
return ans;
}
public void process(char [] str, int index, List<String> ans, String path){
if(index == str.length){
ans.add(path); //如果index来到str终止位置,把沿途路径形成一个答案,放到ans中
return;
}
String no= path;
//index 此时来到的位置,要 or 不要
//不添加
process(str,index+1,ans,no);
String yes = path+String.valueOf(str[index]);
//添加
process(str,index+1,ans,yes);
}
}
字符全部子序列,去掉重复的子序列
package alorithm;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
public class StringProcess {
public List<String> subs(String s){
char[] str = s.toCharArray();
String path = "";
HashSet<String> set = new HashSet<>();
List<String> ans = new ArrayList<>();
process(str,0,set,path);
for(String cur : set){
ans.add(cur);
}
return ans;
}
public void process(char [] str, int index, HashSet<String> set, String path){
if(index == str.length){
set.add(path); //如果index来到str终止位置,把沿途路径形成一个答案,放到ans中
return;
}
String no= path;
//index 此时来到的位置,要 or 不要
//不添加
process(str,index+1,set,no);
String yes = path+String.valueOf(str[index]);
//添加
process(str,index+1,set,yes);
}
}
字符串全排列,去除重复排列
class Solution {
List<String> ans = new LinkedList<>();
char [] str;
public String[] permutation(String s) {
str = s.toCharArray();
dfs(0);
return ans.toArray(new String[ans.size()]);
}
//str[0...i-1]已经做好决定的
//str[i...]都有机会来到i位置
void dfs(int x){
if(x == str.length-1){
ans.add(String.valueOf(str));
}
HashSet<Character> set = new HashSet<>();
for(int i=x;i<str.length;i++){
if(set.contains(str[i]))continue; //重复数字交换还是一样的,剪枝
set.add(str[i]);
swap(str,x,i);
dfs(x+1);
swap(str,x,i);//恢复现场, 一步一步的退回去,回溯
}
}
void swap(char [] str,int i,int j){
char tmp = str[i];
str[i] = str[j];
str[j] = tmp;
}
}
最长不含重复字符的子字符串
class Solution {
public int lengthOfLongestSubstring(String s) {
//动态规划
Map<Character,Integer> map = new HashMap<>();
int res = 0;
int tmp = 0;
for(int i=0;i<s.length();i++){
int n = map.getOrDefault(s.charAt(i),-1);
map.put(s.charAt(i),i);
tmp = tmp<i-n ? tmp+1 : i-n;
res = Math.max(res,tmp);
}
return res;
}
}
手写死锁
两个线程各自持一把锁,然后申请对方持有的锁
package com;
public class DeadLock {
//创建资源
private static Object resourceA = new Object();
private static Object resourceB = new Object();
public static void main(String[] args) {
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
synchronized (resourceA) {
System.out.println(Thread.currentThread() + "获得A");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"等待B");
synchronized (resourceB) {
System.out.println(Thread.currentThread()+"获得B");
}
}
}
});
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
synchronized (resourceB) {
System.out.println(Thread.currentThread() + "获得B");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"等待A");
synchronized (resourceA) {
System.out.println(Thread.currentThread()+"获得A");
}
}
}
});
threadA.start();
threadB.start();
}
}
生产者消费者模式
package com;
import cn.algorithm.ThreadPool;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
import static java.lang.Thread.sleep;
public class ProducerAndConsumer {
public static void main(String[] args) {
MessageQueue messageQueue = new MessageQueue(2);
for (int i=0;i<3;i++){
int id = i;
new Thread(()->{
try {
messageQueue.put(new Message(id,"值"+id));
} catch (InterruptedException e) {
e.printStackTrace();
}
},"生产者"+i).start();
}
new Thread(()->{
try {
while (true){
sleep(1);
Message message = messageQueue.take();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"消费者").start();
}
}
class MessageQueue{
private LinkedList<Message> list = new LinkedList<>();
private int capacity;
public MessageQueue(int capacity){
this.capacity = capacity;
}
public Message take() throws InterruptedException {
//检查队列是否为空
synchronized (list) {
while (list.isEmpty()) {
System.out.println("队列为空,消费者线程等待");
list.wait();
}
Message message = list.removeFirst();
System.out.println("已消费消息"+message);
list.notifyAll();
return message;
}
}
public void put(Message message) throws InterruptedException {
//检查队列是否已满
synchronized (list){
while (list.size()==capacity){
System.out.println("队列已满,生产者线程等待");
list.wait();
}
list.addLast(message);
System.out.println("已生产消息"+message);
list.notifyAll();
}
}
}
final class Message{
private int id;
private Object value;
public Message(int id, Object value) {
this.id = id;
this.value = value;
}
public int getId() {
return id;
}
public Object getValue() {
return value;
}
@Override
public String toString() {
return "Message{" +
"id=" + id +
", value=" + value +
'}';
}
}
手写线程池提交任务
package cn.algorithm;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPool {
public static void main(String[] args) {
String [] s = new String[1];
ExecutorService service = Executors.newFixedThreadPool(10);
Random r = new Random();
service.submit(()->{
for(int i=0;i<=100;i++){
try {
Thread.sleep(r.nextInt(100));
} catch (InterruptedException e) {
e.printStackTrace();
}
s[0] = i+"%";
System.out.print("\r"+Arrays.toString(s));
}
});
}
}
多线程交替打印输出
package cn.algorithm;
public class OneByOne {
public static void main(String[] args) {
WaitNotify wn = new WaitNotify(1,5);
new Thread(()->{
try {
wn.print("a",1,2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(()->{
try {
wn.print("b",2,3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(()->{
try {
wn.print("c",3,1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
class WaitNotify{
//打印输出
public void print(String str,int waitFlag,int nextFlag) throws InterruptedException {
for(int i=0;i<loopNumber;i++) {
synchronized (this) {
while (flag != waitFlag) {
this.wait();
}
System.out.printf(str);
flag = nextFlag;
this.notifyAll();
}
}
}
private int flag;
private int loopNumber;
public WaitNotify(int flag, int loopNumber) {
this.flag = flag;
this.loopNumber = loopNumber;
}
@Override
public String toString() {
return "WaitNotify{" +
"flag=" + flag +
", loopNumber=" + loopNumber +
'}';
}
}