JAVA算法学习初级与进阶

递归复杂度求解

数组求和的递归实现

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 +
                '}';
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。在编写C程序时,需要注意变量的声明和定义、指针的使用、内存的分配与释放等问题。C语言中常用的数据结构包括: 1. 数组:一种存储同类型数据的结构,可以进行索引访问和修改。 2. 链表:一种存储不同类型数据的结构,每个节点包含数据和指向下一个节点的指针。 3. 栈:一种后进先出(LIFO)的数据结构,可以通过压入(push)和弹出(pop)操作进行数据的存储和取出。 4. 队列:一种先进先出(FIFO)的数据结构,可以通过入队(enqueue)和出队(dequeue)操作进行数据的存储和取出。 5. 树:一种存储具有父子关系的数据结构,可以通过中序遍历、前序遍历和后序遍历等方式进行数据的访问和修改。 6. 图:一种存储具有节点和边关系的数据结构,可以通过广度优先搜索、深度优先搜索等方式进行数据的访问和修改。 这些数据结构在C语言中都有相应的实现方式,可以应用于各种不同的场景。C语言中的各种数据结构都有其优缺点,下面列举一些常见的数据结构的优缺点: 数组: 优点:访问和修改元素的速度非常快,适用于需要频繁读取和修改数据的场合。 缺点:数组的长度是固定的,不适合存储大小不固定的动态数据,另外数组在内存中是连续分配的,当数组较大时可能会导致内存碎片化。 链表: 优点:可以方便地插入和删除元素,适用于需要频繁插入和删除数据的场合。 缺点:访问和修改元素的速度相对较慢,因为需要遍历链表找到指定的节点。 栈: 优点:后进先出(LIFO)的特性使得栈在处理递归和括号匹配等问题时非常方便。 缺点:栈的空间有限,当数据量较大时可能会导致栈溢出。 队列: 优点:先进先出(FIFO)的特性使得
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值