目录
最长公共子序列
public int lcs(String s1, String s2) {
int len1 = s1.length();
int len2 = s2.length();
int[][] dp = new int[len1 + 1][len2 + 1];
for (int i = 1; i <= len1; i++) {
for (int j = 1; j <= len2; j++) {
if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1] + 1;
}else{
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[len1][len2];
}
可参考:https://blog.csdn.net/qq_31881469/article/details/77892324
最长公共子串
public int lcs1(String s1, String s2) {
int len1 = s1.length();
int len2 = s2.length();
int[][] dp = new int[len1 + 1][len2 + 1];
int max = 0;
for (int i = 1; i <= len1; i++) {
for (int j = 1; j <= len2; j++) {
if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1] + 1;
}else{
dp[i][j] = 0;
}
max = Math.max(dp[i][j], max);
}
}
return max;
}
最长上升子序列
public int lengthOfLIS(int[] nums) {
if(nums == null || nums.length == 0) return 0;
int[] dp = new int[nums.length];
int max = 1;
Arrays.fill(dp, 1);
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < i; j++) {
if (nums[j]<nums[i]){
dp[i] = Math.max(dp[i],dp[j] + 1);
}
}
max = Math.max(dp[i], max);
}
return max;
}
最长连续上升子序列
public int findLengthOfLCIS(int[] nums) {
if(nums == null || nums.length < 1) return 0;
int[] dp = new int[nums.length];
int max = 1;
Arrays.fill(dp, 1);
for (int i = 1; i < nums.length; i++) {
if (nums[i] > nums[i - 1]) {
dp[i] = dp[i-1]+1;
}
max = Math.max(dp[i], max);
}
return max;
}
最长公共前缀
public String longestCommonPrefix(String[] strs) {
if (strs.length == 0) return "";
String prefix = strs[0];
for (int i = 1; i < strs.length; i++)
while (strs[i].indexOf(prefix) != 0) {
prefix = prefix.substring(0, prefix.length() - 1);
if (prefix.isEmpty()) return "";
}
return prefix;
}
最大子序列和
public int maxSubArray(int[] nums) {
if(nums == null || nums.length == 0) return 0;
int max = nums[0],sum = 0;
for(int i = 0; i < nums.length ; i++){
if(sum > 0 ){
sum += nums[i];
}else{
sum = nums[i];
}
max = Math.max(sum,max);
}
return max;
}
无重复字符的最长子串
public static int lengthOfLongestSubstring(String s) {
Map<Character, Integer> map = new HashMap<>();
int max = 0;
int start = 0;
for(int end = 0;end <s.length();end++) {
char c = s.charAt(end);
if (map.containsKey(c)) {
// 这里必须使用max函数,防止出现输入字符串是abba的这种情况,在最后一次发现a在map中的时候
// 查到的结果为map.get(c)=0,那么start= map.get(c)+1就是1,最后的结果为3,使用max函数
// 就是为了防止start指针后退。
start = Math.max(start, map.get(c)+1);
}
map.put(c, end);
max = Math.max(max, end - start + 1);
}
return max;
}
大数相加
可以参考我的这篇文章 大数相加,大数相乘,下面的重新写的代码没有进行多次翻转,相对简单
public static String add(String s1,String s2) {
String res = "";
int len1 = s1.length();
int len2 = s2.length();
int max = len1>len2?len1:len2;
// 用0补齐到相同长度,方便计算
if(len1 < len2) {
for (int i = 0; i < max - len1; i++) {
s1 = "0" + s1;
}
}else {
for (int i = 0; i < max - len2; i++) {
s2 = "0" + s2;
}
}
int c = 0;//进位
for (int i = max - 1; i >= 0; i--) {
// 减0是可以直接拿到数字大小
int temp = (s1.charAt(i) - '0') + (s2.charAt(i) - '0') + c;
int cur = temp % 10;//这是进位后的个位数
res = cur + res;//将这个数添加到结果中
c = temp / 10;//进位
}
if(c>0) {//判断最后是否有进位大于0,如果有添加
res = c + res;
}
return res;//直接输出,不用反转
}
大数相乘
链表大数相加
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode head = new ListNode(0);
ListNode cur = head,p1=l1,p2=l2;
int carry = 0;
while(p1 != null || p2 != null ){
int x = p1!=null?p1.val:0;
int y = p2!=null?p2.val:0;
int sum = x+y+carry;
carry = sum/10;
cur.next = new ListNode(sum%10);
cur = cur.next;
if(p1!=null) p1 = p1.next;
if(p2!=null) p2 = p2.next;
}
if(carry >0 ){
cur.next = new ListNode(carry);
}
return head.next;
}
两数之和
public int[] twoSum(int[] nums,int target){
HashMap<Integer,Integer> map = new HashMap<>();
for(int i = 0;i<nums.length;i++){
int tmp = target - nums[i];
if(map.containsKey(tmp)){
return new int[]{map.get(tmp),i};
}
map.put(nums[i],i);
}
return new int[2];
}
删除有序链表中的重复元素(只保留一个重复元素)
public ListNode deleteDuplicates(ListNode head) {
ListNode phead = new ListNode(0);
phead.next = head;
ListNode slow = phead,fast = head;
while(fast!=null){
while(fast.next != null && fast.val == fast.next.val) fast = fast.next;
slow.next = fast;
slow = slow.next;
fast = fast.next;
}
return phead.next;
}
数组去重
不考虑最终数组排完序后的数组元素,例如1,1,3,2,2,2,2,2,5,最终去重后数组的元素为1,3,2,5,2,2,2,2,5
public void deleteDup(int[] nums) {
if (nums == null || nums.length == 0) return;
int fast = 0;
int slow = 0;
while (fast < nums.length) {
while (fast + 1 < nums.length && nums[fast] == nums[fast + 1]) fast++;
nums[slow++] = nums[fast++];
}
}
一个数组奇偶分开,偶数在前奇数在后(不要求相对有序)
可参考我的这篇文章给一个数组,把偶数放到左边,奇数放到右边(有序和无序)
public void reOrderArray(int[] nums) {
int less = 0;
int more = nums.length-1;
while (less < more) {
while (nums[more] % 2 == 0) {
swap(nums, more, less++);
}
more--;
}
}
public void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
一个数组奇偶分开,偶数在前奇数在后(要求变换前后相对有序)
public void reOrderArray(int[] array) {
if ( array == null || array.length == 0 ) return;
int left = 0;//从左向右最右边的奇数下标
for (int i = 0; i < array.length; i++) {
if (array[i] % 2 == 0) {
int cur = i;//碰到的偶数
while (cur > left) {//逐个交换位置
swap(array, cur, --cur);
}
left++;//交换完偶数下标向右移动
}
}
}
public void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
数组中除了两个数都只出现一次,其余的都只出现一次
参考这篇(Java)一个整型数组里除了两个数字之外,其他的数字都出现了偶数次。请写程序找出这两个只出现一次的数字。或者leetcode的下面这个回答,相对来说比较简单。
public int[] singleNumber(int[] nums) {
int xor = 0;
for (int i : nums)// 一样的抵消,不一样的两个数字异或运算结果必定有一位是1
xor ^= i;
int mask = xor & (-xor);
int[] ans = new int[2];
for (int i : nums) {
if ((i & mask) == 0)//== 0、 == mask 两种结果
ans[0] ^= i;
else
ans[1] ^= i;
}
return ans;
}
作者:spirit-9
链接:https://leetcode-cn.com/problems/single-number-iii/solution/java-yi-dong-yi-jie-xiao-lu-gao-by-spirit-9-9/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
数组topK
public int topK(int[] nums, int k) {
if (nums == null || k <0 || k>nums.length) return Integer.MIN_VALUE;
PriorityQueue<Integer> queue = new PriorityQueue<>(k);
for (int i = 0; i < nums.length; i++) {
if (queue.size() == k) {
if (queue.peek() < nums[i]) {
queue.poll();
queue.offer(nums[i]);
}
}else {
queue.offer(nums[i]);
}
}
int res = queue.peek();
for (int item : queue) {
res = queue.poll();
}
return res;
}
全排列
46. 全排列,代码中的链接可以看详细讲解。
class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
int[] visited = new int[nums.length];
backtrack(res, nums, new ArrayList<Integer>(), visited);
return res;
}
private void backtrack(List<List<Integer>> res, int[] nums, ArrayList<Integer> tmp, int[] visited) {
if (tmp.size() == nums.length) {
res.add(new ArrayList<>(tmp));
return;
}
for (int i = 0; i < nums.length; i++) {
if (visited[i] == 1) continue;
visited[i] = 1;
tmp.add(nums[i]);
backtrack(res, nums, tmp, visited);
visited[i] = 0;
tmp.remove(tmp.size() - 1);
}
}
}
作者:powcai
链接:https://leetcode-cn.com/problems/permutations/solution/hui-su-suan-fa-by-powcai-2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
两个二叉树是否相等
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p == null && q == null) return true;
if(p == null || q == null) return false;
if(p.val != q.val) return false;
return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
}
二叉树最大值
这题思路就是通过中序遍历,使用优先队列PriorityQueue存储,设置优先队列的大小为1,最后直接可以弹出。
二叉树第K大
和上题的思路就是优先队列的大小设置为K。
树的前序中序后序递归非递归遍历
树变链表
下方链接中有详细思路讲解,很清晰。
public void flatten(TreeNode root) {
while (root != null) {
//左子树为 null,直接考虑下一个节点
if (root.left == null) {
root = root.right;
} else {
// 找左子树最右边的节点
TreeNode pre = root.left;
while (pre.right != null) {
pre = pre.right;
}
//将原来的右子树接到左子树的最右边节点
pre.right = root.right;
// 将左子树插入到右子树的地方
root.right = root.left;
root.left = null;
// 考虑下一个节点
root = root.right;
}
}
}
作者:windliang
链接:https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by--26/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
树的路径总和
public boolean hasPathSum(TreeNode root, int sum) {
if(root == null) return false;
sum -= root.val;
if(root.left == null && root.right == null){
return sum == 0;
}
return hasPathSum(root.left,sum) || hasPathSum(root.right,sum);
}
public List<List<Integer>> pathSum(TreeNode root, int sum) {
List<List<Integer>> res = new ArrayList<>();
helper(root, sum, res, new ArrayList<Integer>());
return res;
}
private void helper(TreeNode root, int sum, List<List<Integer>> res, ArrayList<Integer> tmp) {
if (root == null) return;
tmp.add(root.val);
if (root.left == null && root.right == null && sum - root.val == 0) res.add(new ArrayList<>(tmp));
helper(root.left, sum - root.val, res, tmp);
helper(root.right, sum - root.val, res, tmp);
tmp.remove(tmp.size() - 1);
}
作者:powcai
链接:https://leetcode-cn.com/problems/path-sum-ii/solution/dfs-by-powcai-2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
二叉树的最近公共祖先
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null || root == p || root == q) return root;
TreeNode right = lowestCommonAncestor(root.right,p,q);
TreeNode left = lowestCommonAncestor(root.left,p,q);
if(left == null && right == null) return null;
else if(left != null && right != null) return root;
else return left == null?right:left;
}
快排,归并,冒泡
二分查找递归非递归
青蛙跳台阶
public int climbStairs(int n) {
int[] dp = new int[n+1];
dp[0] = dp[1] = 1;
for(int i = 2; i <= n ;i++){
dp[i] = dp[i-1]+dp[i-2];
}
return dp[n];
}
第一个只出现第一次的字符
public int firstUniqChar(String s) {
int[] help = new int[256];
for(int i = 0;i < s.length();i++){
help[s.charAt(i)]++;
}
for(int i = 0;i<s.length();i++){
if(help[s.charAt(i)] == 1)
return i;
}
return -1;
}
凑硬币
注意:下面的代码并没有解决凑不齐的情况。只是返回凑不齐时最多多少个
public int sumCoin(int[] coins, int amount) {
if (coins == null || coins.length < 1) return -1;
int[] dp = new int[amount+1];
dp[0] = 0;
for (int i = 1; i <= amount; i++) {
dp[i] = amount + 1;
for (int coin : coins) {
if (i >= coin) {
dp[i] = Math.min(dp[i - coin] + 1, dp[i]);
}
}
}
return dp[amount] >amount? -1 : dp[amount];
}
01背包
买卖股票的最佳时机
public int maxProfit(int[] prices) {
if(prices.length == 0) return 0;
int result = 0;
for (int i = 0; i < prices.length-1; i++) {
int temp = prices[i+1] - prices[i];
if( temp>0)
result += temp;
}
return result;
}
括号匹配
public boolean isValid(String s) {
Map<Character, Character> map = new HashMap<>();
Stack<Character> stack = new Stack<>();
stack.push('#');
map.put('(', ')');
map.put('{', '}');
map.put('[', ']');
map.put('#', '#');
for (int i = 0; i < s.length(); i++) {
if (map.containsKey(s.charAt(i))) stack.push(s.charAt(i));
else if (map.get(stack.pop()) != s.charAt(i)) return false;
}
return stack.size() == 1;
}
进制转换
public String transter(int m, int n) {
StringBuilder sb = new StringBuilder();
boolean flag = true;
if (m < 0) {
m = -m;
flag = false;
}
while (m > 0) {
int yu = m % n;
if (yu > 9) {
char temp = (char) (yu - 10 + 'A');
sb.append(temp);
}else {
sb.append(yu);
}
m = m / n;
}
if (!flag) {
sb.append("-");
}
return sb.reverse().toString();
}