算法题-java

dp背包问题

问题:动态规划的优化
给你一个可装载重量为 W 的背包和 N 个物品,每个物品有重量和价值两个属性。其中第 i 个物品的重量为 wt[i],价值为 val[i],现在让你用这个背包装物品,最多能装的价值是多少?
https://markrepo.github.io/algorithm/2021/01/01/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92-%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98/

static int fun(int W, int N, int wt[], int val[]) {<!-- -->
        int[][] dp = new int[N + 1][W + 1];//dp[i][w]表示剩余容量为w时,装入前i个物体。
        for (int i = 1; i <= N; ++i) {<!-- -->
            for (int w = 1; w <= W; ++w) {<!-- -->
                if (w - wt[i - 1] < 0)
                    dp[i][w] = dp[i - 1][w];//当前背包的容量装不下第i个。
                else {<!-- -->
                    dp[i][w] = max(dp[i - 1][w - wt[i - 1]] + val[i - 1], dp[i - 1][w]);
                }                           //装入或者不装入背包,择优。
            }
        }
        for (int i = 1; i <= N; i++) {<!-- -->
            for (int j = 1; j <=W; j++) {<!-- -->
                System.out.print(dp[i][j] + "\t");
            }
            System.out.println();
        }
        return dp[N][W];
    }
二叉树所有路径的拼接

二叉树的每个节点为0-9的一个数字,根到叶子的一条路径拼成一个数,求所有路径形成的数字和

struct TreeNode
{
    TreeNode* left;
    TreeNode* right;
    int value;
};
 
int dfs(TreeNode* root, int sum)
{
    if (root == nullptr)
    {
        return 0;
    }
    if (root->left == nullptr && root->right == nullptr)
    {
        return sum * 10 + root->value;
    }
    return dfs(root->left, sum * 10 + root->value)
         + dfs(root->right, sum * 10 + root->value);
}
 
int SumOfPath(TreeNode* root)
{
    return dfs(root, 0);
}

https://blog.csdn.net/wwj_ff/article/details/46359285

合并两个有序数组

给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 num1 成为一个有序数组。
说明:
初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。
你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n )来保存 nums2 中的元素。
示例:
输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
输出: [1,2,2,3,5,6]

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int len1 = m - 1;
        int len2 = n - 1;
        int len = m + n - 1;
        while(len1 >= 0 && len2 >= 0) {
            // 注意--符号在后面,表示先进行计算再减1,这种缩写缩短了代码
            nums1[len--] = nums1[len1] > nums2[len2] ? nums1[len1--] : nums2[len2--];
        }
        // 表示将nums2数组从下标0位置开始,拷贝到nums1数组中,从下标0位置开始,长度为len2+1
        System.arraycopy(nums2, 0, nums1, 0, len2 + 1);
    }
}

作者:guanpengchn
链接:https://leetcode-cn.com/problems/merge-sorted-array/solution/hua-jie-suan-fa-88-he-bing-liang-ge-you-xu-shu-zu-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
构造完全二叉树
  1. 顺序二叉树通常只考虑完全二叉树;

  2. 第n个元素的左子节点为 2*n +1 ;

  3. 第n个元素的右子节点为:2*n +2;

  4. 第n个元素的父节点为 (n-1)/2;

  5. n 表示二叉树中的第几个元素(按0开始编号).

class Node {   
    public Node leftchild;
    public Node rightchild;
    public int data;

    public Node(int data) {
        this.data = data;
    }

}
public Node initBinTree(int[] arr) {
        if(arr.length == 1) {
            return new Node(arr[0]);
        }
        List<Node> nodeList = new ArrayList<>();
        
        for(int i = 0; i < arr.length; i++) {
            nodeList.add(new Node(arr[i]));
        }
        int temp = 0;
        while(temp <= (arr.length - 2) / 2) {  //注意这里,数组的下标是从零开始的
            if(2 * temp + 1 < arr.length) {
                nodeList.get(temp).leftchild = nodeList.get(2 * temp + 1);
            }
            if(2 * temp + 2 < arr.length) {
                nodeList.get(temp).rightchild = nodeList.get(2 * temp + 2);
            }
            temp++;
        }
        return nodeList.get(0);
       }

https://www.cnblogs.com/gonjan-blog/p/6504668.html

校门外面的树

题目描述
范式大学内有一条长度为 L 的柏油路,路边有一排树,假设长度也是 L 。 如果我们把这条路当作一把直尺,路的一端在 0 的位置,一端在 L 的位置,而且 直尺上的每个整数点都有一棵树。
范式大学要开辟一些区域来建造休息椅和休闲长亭,这些区域用他们在直尺上的起始点和终止点表示。这些点都是整数,区域之间也会有重叠的部分。现在,要把这些准备占用的区域中的树(包括区域端点处的两棵树)移走。
现在请你计算出,把这些“碍事”的树移走之后,这条路上还有多少棵树。

输入
输入的第一行有两个整数 L(1 <= L <= 10000)和 M(1 <= M <= 100),L 代表马路的长度,M 代表区域的数目,L 和 M 之间用一个空格隔开。接下来的 M 行每行包含两个不同的整数,用一个空格隔开,表示一个区域的起始点和终止点 的坐标。

输出
输出包括一行,这一行只包含一个整数,表示马路上剩余的树的数目。

样例输入
500 3
150 300
100 200
470 471
样例输出
298
https://blog.csdn.net/yyl424525/article/details/77859911
构造线段树,插入线段树,算出覆盖区间值

//    线段树的树节点
    class Node {
        int left, right;//左右区间的值
        boolean cover;//表示是否被覆盖
        int count;//表示此节点表示的线段区间出现的次数(被覆盖的次数),默认为0
        Node leftChild;
        Node rightChild;

        Node(int left, int right) {
            this.left = left;
            this.right = right;
            cover=false;
            count = 0;
        }
    }

 /*
   * 外部接口
   * 建立一棵线段树
   * */
    public void build(int left,int right){
        root = new Node(left, right);
        build(root);
    }
    /*
    * 内部接口
    * 建立一棵线段树
    * */
    private void build(Node root) {
        int left = root.left;
        int right = root.right;
        //root节点为叶子节点
        if (right - left == 1) {
            return;
        } else if (right - left > 1) {
            int mid = (left + right) >> 1;将左右区间平分
            Node leftNode = new Node(left, mid);
            Node rightNode = new Node(mid , right);
            root.leftChild = leftNode;
            root.rightChild = rightNode;
//        递归的创建左右子树
            build(leftNode);
            build(rightNode);
        }
    }

 /*
     * 插入一条线段[c,d]的外部接口
     * c为左端点
     * d为右端点
     * root 为此线段树的根节点
     * */
    public void insert(int c, int d) {
    insert(c,d,root);
    }
    /*
    * 插入一条线段[c,d]的内部接口
    * c为左端点
    * d为右端点
    * root 为此线段树的根节点
    * */
 private void insert(int c, int d, Node node) {
       if(node==null||c<node.left||d>node.right){
           System.out.println("输入的参数不合法!"+"c:"+c+" "+"d:"+d);
           System.out.println("root:"+node.left+" "+node.right);

           return ;
       }
       if(node.left==c&&node.right==d)
       {
           node.count++;
           node.cover=true;
           return;
       }
       int mid=(node.left+node.right)>>1;
       if(d<=mid){
           insert(c,d,node.leftChild);
       }

       else if(c>=mid)
           insert(c,d,node.rightChild);
       else {
           insert(c,mid,node.leftChild);
           insert(mid,d,node.rightChild);
       }
    }

 /*
   * 外部接口
   * 统计线段树中cover为true的线段的总长度
   * */
    public int Count(){
        return Count(root);
    }

    /*
    * 内部接口
    * 统计线段树中cover为true的线段的总长度
    * */
    private int Count(Node node){
        if(node.cover==true)//不继续往下查找,否则会重复
            return node.right-node.left;
        else {
            if(node.right-node.left==1)
                return 0;
            else
                return Count(node.leftChild)+Count(node.rightChild);
        }
    }

public class SegmentTreeTest {
    public static void main(String[] args) {
      SegmentTree segmentTree=new SegmentTree();
      //先建立线段树
        segmentTree.build(1,10);
        segmentTree.insert(3,5);
        segmentTree.insert(3,5);
        segmentTree.insert(2,5);
        segmentTree.insert(3,9);
        segmentTree.insert(1,10);
//[2,5]被分为[2,3],[3,5]
//[3,9]被分为[3,5],[5,9]
//[5,9]被分为[5,7],[7,8]+[8,9]
        System.out.println("被覆盖的长度:"+segmentTree.Count());
//        输出为[2,3]+[3,5]+[5,7]+[7,8]+[8,9]=7

    }
}
反序列化二叉树

反序列化(层序遍历)树
// 层序遍历结果 [1, 2, 3, null, 5, null, 6, null, null, 7, null, null, null]
[1, 2, 3, 0, 5, 0, 6, 0, 0, 7, 0, 0, 0]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12]
// 1
// /
// 2 3
// \
// 5 6
// /
// 7

public class Codec {
 
    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        if(root == null)
            return "[]";
        Queue<TreeNode> queue = new LinkedList<>();
        StringBuilder res = new StringBuilder("[");
        queue.add(root);
        while(!queue.isEmpty()){
            TreeNode node = queue.poll();
            if(node != null){
                res.append(node.val + ",");
                queue.add(node.left);
                queue.add(node.right);
            }
            else{
                res.append("null,");
            }
        }
        res.deleteCharAt(res.length() - 1); //删除最后一个逗号
        res.append("]");
        return res.toString();
    }
 
    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        if(data.equals("[]"))   //字符串为空
            return null;
        String[] vals =  data.substring(1,data.length() - 1).split(",");  //将data去掉头尾括号后,按照逗号分隔
        Queue<TreeNode> queue = new LinkedList<>();
        TreeNode root = new TreeNode(Integer.parseInt(vals[0]));
        queue.add(root);
        int i = 1;
        while(!queue.isEmpty()){
            TreeNode node = queue.poll();
            if(!vals[i].equals("null")){    //当序列化字符串此时不为null
                node.left = new TreeNode(Integer.parseInt(vals[i]));
                queue.add(node.left);
            }
            i++;
            if(!vals[i].equals("null")){
                node.right = new TreeNode(Integer.parseInt(vals[i]));
                queue.add(node.right);
            }
            i++;
        }
        return root;
    }
}
    def serialize(self, root):

        s = ""
        queue = []
        queue.append(root)
        while queue:
            root = queue.pop(0)
            if root:
                s += str(root.val)
                queue.append(root.left)
                queue.append(root.right)
            else:
                s += "n"
            s += " "        
        return s

    def deserialize(self, data):
 
        tree = data.split()
        print(tree)
        if tree[0] == "n":
            return None
        queue = []
        root = TreeNode(int(tree[0]))
        queue.append(root)
        i = 1
        while queue:
            cur = queue.pop(0)
            if cur == None:
                continue
            cur.left = TreeNode(int(tree[i])) if tree[i] != "n" else None
            cur.right = TreeNode(int(tree[i + 1])) if tree[i + 1] != "n" else None
            i += 2
            queue.append(cur.left)
            queue.append(cur.right)
        return root
打印二叉树的最右节点
public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
    Queue<TreeNode> queue = new LinkedList<>();
    ArrayList<Integer> ret = new ArrayList<>();
    queue.add(root);
    while (!queue.isEmpty()) {
        int cnt = queue.size();
        while (cnt-- > 0) {
            TreeNode t = queue.poll();
            if (t == null)
                continue;
            if(count == 1){
                ret.add(t.val);
            }
            queue.add(t.left);
            queue.add(t.right);
        }
    }
    return ret;
}

多线程打印奇偶数字

假设有这么一个类:
class ZeroEvenOdd {
public ZeroEvenOdd(int n) { … } // 构造函数
public void zero(printNumber) { … } // 仅打印出 0
public void even(printNumber) { … } // 仅打印出 偶数
public void odd(printNumber) { … } // 仅打印出 奇数
}
相同的一个 ZeroEvenOdd 类实例将会传递给三个不同的线程:

线程 A 将调用 zero(),它只输出 0 。
线程 B 将调用 even(),它只输出偶数。
线程 C 将调用 odd(),它只输出奇数。
每个线程都有一个 printNumber 方法来输出一个整数。请修改给出的代码以输出整数序列 010203040506… ,其中序列的长度必须为 2n。
链接:https://leetcode-cn.com/problems/print-zero-even-odd。

class ZeroEvenOdd {
    private int n;

    public ZeroEvenOdd(int n) {
        this.n = n;
    }

    //定义Lock
    private Lock lock = new ReentrantLock();
    //定义Condition
    private Condition conditionZero = lock.newCondition();
    private Condition conditionEven = lock.newCondition();
    private Condition conditionOdd = lock.newCondition();

    //定义标记
    private static int number = 0;

    // printNumber.accept(x) outputs "x", where x is an integer.
    //打印0
    public void zero(IntConsumer printNumber) throws InterruptedException {
        lock.lock();
        try {
            for (int i = 1; i <= n; i++) {
                if (number != 0) {
                    //zero线程等待
                    conditionZero.await();
                }
                printNumber.accept(0);
                if (i % 2 == 1) {
                    number = 1;
                    //唤醒odd线程
                    conditionOdd.signal();
                } else {
                    number = 2;
                    //唤醒even线程
                    conditionEven.signal();
                }
            }
        } finally {
            lock.unlock();
        }
    }

    //打印偶数
    public void even(IntConsumer printNumber) throws InterruptedException {
        lock.lock();
        try {
            for (int i = 2; i <= n; i += 2) {
                if (number != 2) {
                    //even线程等待
                    conditionEven.await();
                }
                printNumber.accept(i);
                number = 0;
                //唤醒zero线程
                conditionZero.signal();
            }
        } finally {
            lock.unlock();
        }
    }

    //打印奇数
    public void odd(IntConsumer printNumber) throws InterruptedException {
        lock.lock();
        try {
            for (int i = 1; i <= n; i += 2) {
                if (number != 1) {
                    //odd线程等待
                    conditionOdd.await();
                }
                printNumber.accept(i);
                number = 0;
                //唤醒zero线程
                conditionZero.signal();
            }
        }finally {
            lock.unlock();
        }
    }

}


作者:skyshine94
链接:https://leetcode-cn.com/problems/print-zero-even-odd/solution/da-yin-ling-yu-qi-ou-shu-by-skyshine94-xvab/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

https://segmentfault.com/a/1190000037495406

三种方式:1、传统方式;2、加锁;3、信号量
https://www.yisu.com/zixun/542327.html

class ZeroEvenOdd {
	  private volatile int flag = 0;
	
	  private volatile int n;
	  
	  private AtomicInteger i;
	
	  //构造函数
	  public ZeroEvenOdd(int n) {
		  this.n = n;
		  this.i = new AtomicInteger(1);
	  }      
	  
	  //仅打印出 0
	  public void zero(Runnable printNumber) {
		  for(int k = 0; k < n; k++) {
			synchronized (this) {
				try {
					while(0 != this.flag) {
						this.wait();
					}
					
					printNumber.run();
					
					flag = 1;
				} 
				catch (InterruptedException e) {
					e.printStackTrace();
				}
				finally {
					this.notifyAll();
				}
			}
		 }
	  } 
	  
	  //仅打印出 偶数
	  public void even(Consumer<Integer> printNumber) {
		  for(int k = 0; k < n; k++) {
				synchronized (this) {
					try {
						while(1 != this.flag) {
							this.wait();
						}
						
						if(this.i.get() % 2 == 0) {
							printNumber.accept(this.i.get());
							this.i.incrementAndGet();
							flag = 0;
						}
						else {
							flag = 2;
						}
						
						this.notifyAll();
					} 
					catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
		  }
	  }

	  //仅打印出 奇数
	  public void odd(Consumer<Integer> printNumber) {
		  for(int k = 0; k < n; k++) {
				synchronized (this) {
					try {
						while(2 != this.flag) {
							this.wait();
						}
						
						printNumber.accept(this.i.get());
						
						this.i.incrementAndGet();
						
						flag = 0;
						
						this.notifyAll();
					} 
					catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
		 }
	}
}

加锁的

class ZeroEvenOdd2 {
	  private final Lock lock = new ReentrantLock();
	  
	  final Condition zeroCd = lock.newCondition();
	  final Condition evenCd = lock.newCondition();
	  final Condition oddCd = lock.newCondition();
	
	  private volatile int flag = 0;
	
	  private volatile int n;
	  
	  private AtomicInteger i;
	
	  //构造函数
	  public ZeroEvenOdd2(int n) {
		  this.n = n;
		  this.i = new AtomicInteger(1);
	  }      
	  
	  //仅打印出 0
	  public void zero(Runnable printNumber) {
		  for(int k = 0; k < n; k++) {
				try {
					lock.lock();
					
					while(0 != this.flag) {
						zeroCd.await();
					}
					
					printNumber.run();
					
					flag = 1;
					
					evenCd.signal();
				} 
				catch (InterruptedException e) {
					e.printStackTrace();
				}
				finally {
					lock.unlock();
				}
			}
	  } 
	  
	  //仅打印出 偶数
	  public void even(Consumer<Integer> printNumber) {
		  for(int k = 0; k < n; k++) {
				try {
					lock.lock();
					
					while(1 != this.flag) {
						evenCd.await();
					}
					
					if(this.i.get() % 2 == 0) {
						printNumber.accept(this.i.get());
						this.i.incrementAndGet();
						flag = 0;
						zeroCd.signal();
					}
					else {
						flag = 2;
						oddCd.signal();
					}
				} 
				catch (InterruptedException e) {
					e.printStackTrace();
				}
				finally {
					lock.unlock();
				}
			}
	  }

	  //仅打印出 奇数
	  public void odd(Consumer<Integer> printNumber) {
		  for(int k = 0; k < n; k++) {
				try {
					lock.lock();
					
					while(2 != this.flag) {
						oddCd.await();
					}
					
					printNumber.accept(this.i.get());
					
					this.i.incrementAndGet();
					
					flag = 0;
					
					zeroCd.signal();
				} 
				catch (InterruptedException e) {
					e.printStackTrace();
				}
				finally {
					lock.unlock();
				}
			}
	}
}

信号量的

class ZeroEvenOdd3 {
	  private final Semaphore zeroSp = new Semaphore(1);
	  private final Semaphore evenSp = new Semaphore(0);
	  private final Semaphore oddSp = new Semaphore(0);
	  
	  private volatile int n;
	  
	  private AtomicInteger i;
	
	  //构造函数
	  public ZeroEvenOdd3(int n) {
		  this.n = n;
		  this.i = new AtomicInteger(1);
	  }      
	  
	  //仅打印出 0
	  public void zero(Runnable printNumber) {
		  for(int k = 0; k < n; k++) {
				try {
					zeroSp.acquire();
					
					printNumber.run();
				} 
				catch (InterruptedException e) {
					e.printStackTrace();
				}
				finally {
					evenSp.release();
				}
		  }
	  } 
	  
	  //仅打印出 偶数
	  public void even(Consumer<Integer> printNumber) {
		  for(int k = 0; k < n; k++) {
				try {
					evenSp.acquire();
					
					if(this.i.get() % 2 == 0) {
						printNumber.accept(this.i.get());
						this.i.incrementAndGet();
						zeroSp.release();
					}
					else {
						oddSp.release();
					}
				} 
				catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
	  }

	  //仅打印出 奇数
	  public void odd(Consumer<Integer> printNumber) {
		  for(int k = 0; k < n; k++) {
				try {
					oddSp.acquire();
					
					printNumber.accept(this.i.get());
					
					this.i.incrementAndGet();
					
				} 
				catch (InterruptedException e) {
					e.printStackTrace();
				}
				finally {
					zeroSp.release();
				}
			}
	}
}
实现可以自动扩容的arrayList
class ArrayList {
public ArrayList() {}
public Object get(int index) {
  //获取index值
  if(ArrayList.get_by_key == index){
    //通过index获取value值
    return ArrayList.get_by_key(index);
  }
}
public void add(Object o) {
  //加入元素o,先判断arraylist的容量,假设之前赋值的是SIZE
  if(ArrayList.size < SIZE){
    //直接arraylist末尾位置里面加上该元素
    ArrayList.put(o);
  }else{
    //容量超过预设值,进行扩容,思路是进行分配更大的空间,然后复制原来的元素,再往里添加元素
    ArrayList.size = SIZE * 1.5;
    for(int i = 0; i < size; i ++){
      for(int j = 0; j < size * 1.5; j ++)
          ArrayList.get_value_by_key(i) = ArrayList.get_value_by_key(j);
    }
    //在新空间的当前末尾位置加上元素
    ArrayList.put(o);
  }
}
}

https://blog.csdn.net/huangfan322/article/details/52685922

public boolean add(E e) {
    ensureCapacityInternal(size + 1);
    elementData[size++] = e;//添加对象时,自增size
    return true;
}
private void ensureCapacityInternal(int minCapacity) {
    modCount++;//定义于ArrayList的父类AbstractList,用于存储结构修改次数
    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}  
private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);//新容量扩大到原容量的1.5倍,右移一位相关于原数值除以2。
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;//MAX_ARRAY_SIZE和Integer.MAX_VALUE为常量,详细请参阅下面的注解
}
快排
    private static int partition(int[] arr, int left, int right) {
        int temp = arr[left];
        while (right > left) {
            // 先判断基准数和后面的数依次比较
            while (temp <= arr[right] && left < right) {
                --right;
            }
            // 当基准数大于了 arr[right],则填坑
            if (left < right) {
                arr[left] = arr[right];
                ++left;
            }
            // 现在是 arr[right] 需要填坑了
            while (temp >= arr[left] && left < right) {
                ++left;
            }
            if (left < right) {
                arr[right] = arr[left];
                --right;
            }
        }
        arr[left] = temp;
        return left;
    }

    private static void quickSort(int[] arr, int left, int right) {
        if (arr == null || left >= right || arr.length <= 1)
            return;
        int mid = partition(arr, left, right);
        quickSort(arr, left, mid);
        quickSort(arr, mid + 1, right);
    }



作者:nanchen2251
链接:https://juejin.cn/post/6844903642042990599
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
全排列
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
public class Solution {
    public ArrayList<String> Permutation(String str) {
       List<String> resultList = new ArrayList<>();
        if(str.length() == 0){
            return (ArrayList) resultList;
        }
        fun(str.toCharArray(), resultList, 0);
        Collections.sort(resultList);
        return (ArrayList)resultList;
    }
    private void fun(char[] ch, List<String> list, int i){
        if(i == ch.length -1){
            if(!list.contains(new String(ch))){
                list.add(new String(ch));
                return;
            }
        }else{
            for(int j = i; j < ch.length; j ++){
                swap(ch, i, j);
                fun(ch, list, i + 1);
                swap(ch, i, j);
            }
        }
    }
    private void swap(char[] ch, int i, int j){
        char t = ch[i];
        ch[i] = ch[j];
        ch[j] = t;
    }
}
二叉查找树的给定节点删除

leetcode 450:https://leetcode-cn.com/problems/delete-node-in-a-bst/submissions/

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        if(root == null){
            return null;
        }
        if(key < root.val){
            root.left = deleteNode(root.left, key);
        }else if(key > root.val){
            root.right = deleteNode(root.right, key);
        }else{
            if(root.left == null){
                return root.right;
            }else if(root.right == null){
                return root.left;
            }else{
                root.val = minNode(root.right);
                root.right = deleteNode(root.right, root.val);
            }              
        }
        return root;
    }
    private int minNode(TreeNode node){
        while(node.left != null){
            node = node.left;
        }
        return node.val;
    }
}
反转单链表

递归:

public ListNode ReverseList(ListNode head) {
    if (head == null || head.next == null)
        return head;
    ListNode next = head.next;
    head.next = null;
    ListNode newHead = ReverseList(next);
    next.next = head;
    return newHead;
}

非递归:

public ListNode ReverseList(ListNode head) {
    ListNode newList = new ListNode(-1);
    while (head != null) {
        ListNode next = head.next;
        head.next = newList.next;
        newList.next = head;
        head = next;
    }
    return newList.next;
}
最大序列和
//分治算法 
int a[999999];

int MAxSubSum(int left,int right)
{
    int sum=0;
    if(left==right)//基本情况:只有一个元素 
        sum=a[left]>0?a[left]:0;
    else
    {
        int center=(left+right)/2;
        int leftsum=MaxSubSum(left,center);//左半部分 
        int rightsum=MAxSubSum(center+1,right);//右半部分 
        
        //求包含左半部分最右元素的最大和 
        int s1=0;
        int lefts=0;
        for(int i=center;i>=left;i--)
        {
            lefts+=a[i];
            if(lefts>s1) s1=lefts;
        }
        
        //求包含右半部分最左元素的最大和 
        int s2=0;
        int rights=0;
        for(int i=center+;i<=right;i++)
        {
            rights+=a[i];
            if(rights>s2) s2=rights;
        }
        
        //取三者最大值 
        sum=s1+s2;
        if(sum<leftsum) sum=leftsum;
        if(sum<rightsum) sum=rightsum;
    }
    return sum;
}

动态规划求解

//动态规划算法
int maxSubArray(int[] nums) {
    int n = nums.length;
    if (n == 0) return 0;
    int[] dp = new int[n];
    // base case
    // 第一个元素前面没有子数组
    dp[0] = nums[0];
    // 状态转移方程
    for (int i = 1; i < n; i++) {
        dp[i] = Math.max(nums[i], nums[i] + dp[i - 1]);
    }
    // 得到 nums 的最大子数组
    int res = Integer.MIN_VALUE;
    for (int i = 0; i < n; i++) {
        res = Math.max(res, dp[i]);
    }
    return res;
}

优化之后的动态规划
int maxSubArray(int[] nums) {
    int n = nums.length;
    if (n == 0) return 0;
    // base case
    int dp_0 = nums[0];
    int dp_1 = 0, res = dp_0;

    for (int i = 1; i < n; i++) {
        // dp[i] = max(nums[i], nums[i] + dp[i-1])
        dp_1 = Math.max(nums[i], nums[i] + dp_0);
        dp_0 = dp_1;
        // 顺便计算最大的结果
        res = Math.max(res, dp_1);
    }
    
    return res;
}
LRU cache

key是内存地址
value是内存存放的值
双向链表记录顺序位置,head,tail
hashmap用于查询链表中是否有我们想要找的数据,get的时候

get方法:有这个数据的话,返回这个数据,并把这个数据放到最前面,没有就返回-1;
put方法:往cache放入数据,没有超出容量则放到第一位,超出了就删掉最后一个数据,再把当前的数据放到最前面

class linkNode{
    int key;
    int val;
    linkNode front;
    linkNode next;
    public linkNode(int key, int val){
        this.key = key;
        this.val = val;
    }

}
class LRUCache {
    int capacity;
    Map<Integer, linkNode> map = new HashMap<>();
    linkNode head = new linkNode(0, 0);
    linkNode tail = new linkNode(0, 0);
    public LRUCache(int capacity) {
        this.capacity = capacity;
        head.next = tail;
        tail.front = head;
    }
    
    public int get(int key) {
        if(map.containsKey(key)){
            linkNode node = map.get(key);
            moveNodeToTop(node);
            return node.val;
        }else{
            return -1;
        }

    }
    
    public void put(int key, int value) {
        if(!map.containsKey(key)){
            if(map.size() == capacity){
                //容量满了,删除最后一个节点
                deleteLastNode();
            }  
            linkNode temp = head.next;
            linkNode newNode = new linkNode(key, value);
            head.next = newNode;
            newNode.front = head;
            newNode.next = temp;
            temp.front = newNode;
            map.put(key, newNode);
        }else{
            linkNode node = map.get(key);
            node.val = value;
            //把当前节点放到最前面
            moveNodeToTop(node);
        }

    }
    private void deleteLastNode(){
        /**
        if(tail != null){
            linkNode lastNode = tail.front;
            if(lastNode == null){
                head = null;
            }else{
                lastNode.front.next = tail;
                tail.front = lastNode.front;
                map.remove(lastNode.key);
            }
        }
         */
        linkNode lastNode = tail.front;
        lastNode.front.next = tail;
        tail.front = lastNode.front;
        map.remove(lastNode.key);
    }
    private void moveNodeToTop(linkNode node){
        node.front.next = node.next;
        node.next.front = node.front;
        linkNode temp = head.next;
        head.next = node;
        node.front = head;
        node.next = temp;
        temp.front = 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);
 */

用单例模式实现,加volatile关键字可以实现并发
http://shangdixinxi.com/detail-1539958.html

public class LRUCache extends LinkedHashMap<String, String> {

    private int cache_size;

    private static volatile LRUCache instance;

    private LRUCache(int capacity) {
        super(capacity, 0.75f, true);
        this.cache_size = capacity;

    }

    public static synchronized LRUCache getInstance() {
        if (instance == null) {
            instance = new LRUCache(100);
        }
        return instance;
    }

    public String get(String key) {
        synchronized (this) {
            return super.getOrDefault(key, "");
        }
    }

    public String put(String key, String value) {
        synchronized (this) {
            return super.put(key, value);
        }
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
        return this.size() > cache_size;
    }
}

红黑树

https://juejin.cn/post/6844903454767317005

BTS的删除节点

https://blog.csdn.net/u011240877/article/details/53242179

41. 缺失的第一个正数

nums[i] = i + 1
https://leetcode-cn.com/problems/first-missing-positive/submissions/

class Solution {
    public int firstMissingPositive(int[] nums) {
        for(int i = 0; i < nums.length; i ++){
            while(nums[i] > 0 && nums[i] < nums.length && nums[nums[i] - 1] != nums[i]){
                swap(nums, nums[i] - 1, i);
            }
        }
        for(int i = 0; i < nums.length; i ++){
            if(nums[i] != i + 1){
                return i + 1;
            }
        }
        return nums.length + 1;

    }

    private void swap(int[] nums, int i, int j){
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}
字符的全组合
/*
 * AllQ.java 2011-10-23
 * Copyright 2010 - 2011 
 */
package java_string;
 
/*字符串的所有组合*/
 
public class AllQ {
 
	/**
	 * @param args
	 */
	public static void combination(String str, int index, int number,
			StringBuilder sb) {
		if (number == -1 ) {
			System.out.println(sb.toString());
			return;
		}
		if (index == str.length())
			return;
 
		sb.append(str.charAt(index));
 
		combination(str, index + 1, number - 1, sb);
 
		sb.deleteCharAt(sb.length() - 1);
 
		combination(str, index + 1, number, sb);
 
	}
 
	public static void combine(String str) {
		if (str == null)
			return;
		int length = str.length();
		StringBuilder sb = new StringBuilder();
 
		for (int i = 0; i < length; i++) {
			combination(str, 0, i, sb);
		}
	}
 
	public static void main(String[] args) {
		// TODO Auto-generated method stub
 
		combine("abcd");
 
	}
 
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值