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)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
构造完全二叉树
-
顺序二叉树通常只考虑完全二叉树;
-
第n个元素的左子节点为 2*n +1 ;
-
第n个元素的右子节点为:2*n +2;
-
第n个元素的父节点为 (n-1)/2;
-
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");
}
}