一、选m个数和为n
public static void main(String[] args) {
int k=3;
int n=9;
List<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
combinationSum3(k, n, result, path);
System.out.println(result);
}
public static List<List<Integer>> combinationSum3(int k, int n,List<List<Integer>> result,LinkedList<Integer> path) {
build(k,n, 1, 0,result,path);
return result;
}
private static void build(int k, int n, int startIndex, int sum,List<List<Integer>> result,LinkedList<Integer> path) {
if (sum > n) return;
if (path.size() > k) return;
if (sum == n && path.size() == k) {
result.add(new ArrayList<>(path));
return;
}
for(int i = startIndex; i <= 9; i++) {
path.add(i);
sum += i;
build(k, n, i + 1, sum,result,path);
sum -= i;
path.removeLast();
}
}
二、判断回文字段_去除空格
public static void main(String[] args) {
String s="A m2an, a plan, a canal: Pana2ma";
boolean palindrome = isPalindrome(s);
System.out.println(palindrome);
}
//即需要只留下字母和数字进行比较
public static boolean isPalindrome(String s) {
int n = s.length();
int left = 0, right = n - 1;
while (left < right) {
while (left < right && !Character.isLetterOrDigit(s.charAt(left))) {
++left;
}
while (left < right && !Character.isLetterOrDigit(s.charAt(right))) {
--right;
}
if (Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))) {
return false;
}
++left;
--right;
}
return true;
}
三、最长不重复子串
public static void main(String[] args) {
String s="abcdddae";
int res = lengthOfLongestSubstring(s);
System.out.println(res);
}
public static int lengthOfLongestSubstring(String s) {
// 哈希集合,记录每个字符是否出现过
Set<Character> occ = new HashSet<Character>();
int n = s.length();
// 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
int rk = -1, ans = 0;
for (int i = 0; i < n; ++i) {
if (i != 0) {
// 左指针向右移动一格,移除一个字符
occ.remove(s.charAt(i - 1));
}
while (rk + 1 < n && !occ.contains(s.charAt(rk + 1))) {
// 不断地移动右指针
occ.add(s.charAt(rk + 1));
++rk;
}
// 第 i 到 rk 个字符是一个极长的无重复字符子串
ans = Math.max(ans, rk - i + 1);
}
return ans;
}
四、输出两字符串的公共最长子字符串
public static void main(String[] args) {
String s1="abce";
String s2="cabcc";
int res=longestCommonSubsequence(s1,s2);
System.out.println(res);
}
//输出重合子字符串长度
public static int longestCommonSubsequence(String text1, String text2) {
int m = text1.length(), n = text2.length();
int[][] dp = new int[m + 1][n + 1];
for (int i = 1; i <= m; i++) {
char c1 = text1.charAt(i - 1);
for (int j = 1; j <= n; j++) {
char c2 = text2.charAt(j - 1);
if (c1 == c2) {
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[m][n];
}
五、重复的子字符串
//KMP
public static void main(String[] args) {
String s="abcabce";
boolean b = kmp(s);
System.out.println(b);
}
public static boolean kmp(String pattern) {
int n = pattern.length();
int[] fail = new int[n];
Arrays.fill(fail, -1);
for (int i = 1; i < n; i++) {
int j = fail[i - 1];
//前后缀不相同时,j进行回退
while (j != -1 && pattern.charAt(j + 1) != pattern.charAt(i)) {
j = fail[j];
}
//前后缀相同时,得到这个i对应的最长前后缀长度数
if (pattern.charAt(j + 1) == pattern.charAt(i)) {
fail[i] = j + 1;
}
}
return fail[n - 1] != -1 && n % (n - fail[n - 1] - 1) == 0;
}
//暴力
public static void main(String[] args) {
String s="ababc";
boolean b = repeatedSubstringPattern(s);
System.out.println(b);
}
public static boolean repeatedSubstringPattern(String s) {
return (s + s).indexOf(s, 1) != s.length();
}
六、找出超过序列长度一半的整数元素
//Boyer-Moore 投票算法
//关键点:能够确定这个数组里有超过长度一半的整数的前提下,才可用,如果没有的话无法输出null
public static void main(String[] args) {
int[] arr={1,2,2,2,2,2,5,7,8};
int res=majorityElement(arr);
System.out.println(res);
}
public static int majorityElement(int[] nums) {
int count = 0;
Integer candidate = null;
for (int num : nums) {
if (count == 0) {
candidate = num;
}
count += (num == candidate) ? 1 : -1;
}
return candidate;
}
七、二叉树的最近公共祖先
public static void main(String[] args) {
Integer[] arr = new Integer[]{3,5,1,6,2,0,8,null,null,7,4};
TreeNode a=createTree(arr,0);
TreeNode res=lowestCommonAncestor(a,a.left.left,a.left.right.left);
System.out.println(res.val);
}
public static TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == p || root == q || root == null) return root;
//寻找左子树是否包含p和q
TreeNode left = lowestCommonAncestor(root.left, p, q);
//寻找右子树是否包含p和q
TreeNode right = lowestCommonAncestor(root.right, p, q);
// 如果left 和 right都不为空,说明此时root就是最近公共节点
// 如果left为空,right不为空,就返回right,说明目标节点是通过right返回的,反之亦然。
if (left != null && right != null) return root;
if (left == null) return right;
return left;
}
private static TreeNode createTree(Integer[] array,int index){
TreeNode treeNode = null;
if (index<array.length) {
Integer value = array[index];
if (value == null) {
return null;
}
treeNode = new TreeNode(value);
treeNode.left = createTree(array, 2*index+1);
treeNode.right = createTree(array, 2*index+2);
return treeNode;
}
return treeNode;
}
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode() {}
public TreeNode(int val) {
this.val = val;
}
public TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
八、反转字符串的单个单词
class Solution {
public String reverseWords(String s) {
// 除去开头和末尾的空白字符
s = s.trim();
// 正则匹配连续的空白字符作为分隔符分割
List<String> wordList = Arrays.asList(s.split("\\s+"));
Collections.reverse(wordList);
return String.join(" ", wordList);
}
}
九、树的类创建以及层序遍历
//创建二叉树类
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode() {}
public TreeNode(int val) {
this.val = val;
}
public TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
//数组->二叉树
private static TreeNode createTree(Integer[] array,int index){
TreeNode treeNode = null;
if (index<array.length) {
Integer value = array[index];
if (value == null) {
return null;
}
treeNode = new TreeNode(value);
treeNode.left = createTree(array, 2*index+1);
treeNode.right = createTree(array, 2*index+2);
return treeNode;
}
return treeNode;
}
//二叉树的最近公共
public static TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == p || root == q || root == null) return root;
//寻找左子树是否包含p和q
TreeNode left = lowestCommonAncestor(root.left, p, q);
//寻找右子树是否包含p和q
TreeNode right = lowestCommonAncestor(root.right, p, q);
// 如果left 和 right都不为空,说明此时root就是最近公共节点
// 如果left为空,right不为空,就返回right,说明目标节点是通过right返回的,反之亦然。
if (left != null && right != null) return root;
if (left == null) return right;
return left;
}
public class 层序遍历 {
public static void main(String[] args) {
TreeNode a=new TreeNode(5);
a.left=new TreeNode(4);
a.right=new TreeNode(3);
a.left.left=new TreeNode(2);
a.left.right=new TreeNode(1);
ArrayList<ArrayList<Integer>> res=levelOrder(a);
System.out.println(res);
}
public static ArrayList<ArrayList<Integer>> levelOrder (TreeNode root) {
// write code here
ArrayList<ArrayList<Integer> > res = new ArrayList();
if (root == null)
//如果是空,则直接返回空数组
return res;
//队列存储,进行层次遍历
Queue<TreeNode> q = new ArrayDeque<TreeNode>();
q.add(root);
while (!q.isEmpty()) {
//记录二叉树的某一行
ArrayList<Integer> row = new ArrayList();
int n = q.size();
//因先进入的是根节点,故每层节点多少,队列大小就是多少
for (int i = 0; i < n; i++) {
TreeNode cur = q.poll();
row.add(cur.val);
//若是左右孩子存在,则存入左右孩子作为下一个层次
if (cur.left != null)
q.add(cur.left);
if (cur.right != null)
q.add(cur.right);
}
//每一层加入输出
res.add(row);
}
return res;
}
}
十、合并两个有序数列
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int p1 = 0, p2 = 0;
int[] sorted = new int[m + n];
int cur;
while (p1 < m || p2 < n) {
if (p1 == m) {
cur = nums2[p2++];
} else if (p2 == n) {
cur = nums1[p1++];
} else if (nums1[p1] < nums2[p2]) {
cur = nums1[p1++];
} else {
cur = nums2[p2++];
}
sorted[p1 + p2 - 1] = cur;
}
for (int i = 0; i != m + n; ++i) {
nums1[i] = sorted[i];
}
}
}
十一、链表
public static void main(String[] args) {
Node n1 = new Node(1);
Node n2 = new Node(1);
Node n3 = new Node(3);
Node n4 = new Node(4);
Node n5 = new Node(5);
n1.next = n2;
n2.next = n3;
n3.next = n4;
n4.next = n5;
showLink(deleteDuplicates(n1));
}
private static class Node {
Integer value;
Node next;
public Node(){}
public Node(Integer value) {
this.value = value;
}
}
//合并两个有序链表
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode prehead = new ListNode(-1);
ListNode prev = prehead;
while (l1 != null && l2 != null) {
if (l1.val <= l2.val) {
prev.next = l1;
l1 = l1.next;
} else {
prev.next = l2;
l2 = l2.next;
}
prev = prev.next;
}
// 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
prev.next = l1 == null ? l2 : l1;
return prehead.next;
}