leetcode
1、. 分隔链表
给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。
你应当保留两个分区中每个节点的初始相对位置。
示例:
输入: head = 1->4->3->2->5->2, x = 3 输出: 1->2->2->4->3->5
双指针法:
直觉
我们可以用两个指针before 和 after 来追踪上述的两个链表。两个指针可以用于分别创建两个链表,然后将这两个链表连接即可获得所需的链表。
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode partition(ListNode head, int x) { ListNode before_head=new ListNode(-1); ListNode before=before_head; ListNode after_head=new ListNode(-1); ListNode after=after_head; while(head!=null){ if(head.val<x){ before.next=head; before=before.next; }else{ after.next=head; after=after.next; } head=head.next; } after.next=null; before.next=after_head.next; return before_head.next; } }
3、解码方法
一条包含字母 A-Z
的消息通过以下方式进行了编码:
'A' -> 1
'B' -> 2
...
'Z' -> 26
给定一个只包含数字的非空字符串,请计算解码方法的总数。
示例 1:
输入: "12"
输出: 2
解释: 它可以解码为 "AB"(1 2)或者 "L"(12)。
示例 2:
输入: "226"
输出: 3
解释: 它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。
![](https://img2020.cnblogs.com/blog/2033973/202007/2033973-20200729093852517-1166595325.png)
class Solution { public int numDecodings(String s) { if(s.charAt(0)=='0')return 0; char[] c=s.toCharArray(); int dp_2=1; //dp[-1]=1; int dp_1=1; //dp[0]=1; int dp_0=1; for(int i=1;i<c.length;i++){ if(c[i]=='0'){ if(c[i-1]=='1'||c[i-1]=='2') { dp_0=dp_2; //dp[i]=dp[i-2]; } else return 0; }else if(c[i-1]=='1'||(c[i-1]=='2'&&c[i]>'0'&&c[i]<'7')){ dp_0=dp_2+dp_1; //dp[i]=dp[i-2]+dp[i-1]; } dp_2=dp_1; dp_1=dp_0; } return dp_0; } }
3、 不同的二叉搜索树 II
给定一个整数 n,生成所有由 1 ... n 为节点所组成的 二叉搜索树 。
示例:
输入:3 输出: [ [1,null,3,2], [3,2,null,1], [3,1,null,null,2], [2,1,3], [1,null,2,null,3] ] 解释: 以上的输出对应以下 5 种不同结构的二叉搜索树: 1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3
public List<TreeNode> generateTrees(int n) {
ArrayList<TreeNode>[] dp = new ArrayList[n + 1];
dp[0] = new ArrayList<TreeNode>();
if (n == 0) {
return dp[0];
}
dp[0].add(null);
//长度为 1 到 n
for (int len = 1; len <= n; len++) {
dp[len] = new ArrayList<TreeNode>();
//将不同的数字作为根节点,只需要考虑到 len
for (int root = 1; root <= len; root++) {
int left = root - 1; //左子树的长度
int right = len - root; //右子树的长度
for (TreeNode leftTree : dp[left]) {
for (TreeNode rightTree : dp[right]) {
TreeNode treeRoot = new TreeNode(root);
treeRoot.left = leftTree;
//克隆右子树并且加上偏差
treeRoot.right = clone(rightTree, root);
dp[len].add(treeRoot);
}
}
}
}
return dp[n];
}
private TreeNode clone(TreeNode n, int offset) {
if (n == null) {
return null;
}
TreeNode node = new TreeNode(n.val + offset);
node.left = clone(n.left, offset);
node.right = clone(n.right, offset);
return node;
}
4、 不同的二叉搜索树
给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?
示例:
输入: 3
输出: 5
解释:
给定 n = 3, 一共有 5 种不同结构的二叉搜索树:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
![](https://img2020.cnblogs.com/blog/2033973/202007/2033973-20200729100927999-1188074760.png)
class Solution {
public int numTrees(int n) {
int[] dp = new int[n+1];
dp[0] = 1;
dp[1] = 1;
for(int i = 2; i < n + 1; i++)
for(int j = 1; j < i + 1; j++)
dp[i] += dp[j-1] * dp[i-j];
return dp[n];
}
}
5、 完全平方数
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...
)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
示例 1:
输入: n = 12
输出: 3
解释: 12 = 4 + 4 + 4.
示例 2:
输入: n = 13
输出: 2
解释: 13 = 4 + 9.
解题方案
思路:
标签:动态规划
首先初始化长度为n+1的数组dp,每个位置都为0
如果n为0,则结果为0
对数组进行遍历,下标为i,每次都将当前数字先更新为最大的结果,即dp[i]=i,比如i=4,最坏结果为4=1+1+1+1即为4个数字
动态转移方程为:dp[i] = MIN(dp[i], dp[i - j * j] + 1),i表示当前数字,j*j表示平方数
时间复杂度:O(n*sqrt(n)),sqrt为平方根
代码:
class Solution {
public int numSquares(int n) {
int[] dp = new int[n + 1]; // 默认初始化值都为0
for (int i = 1; i <= n; i++) {
dp[i] = i; // 最坏的情况就是每次+1
for (int j = 1; i - j * j >= 0; j++) {
dp[i] = Math.min(dp[i], dp[i - j * j] + 1); // 动态转移方程
}
}
return dp[n];
}
}