文章目录
- 1.两数相加
- 2.寻找两个有序数组的中位数
- 3.最长回文子串
- 4.整数反转
- 5.字符串转为整数
- 6.回文数
- 7.乘最多水的容器
- 8.最长公共前缀
- 9.三数之和
- 10.最接近三数之和
- 11.有效的括号
- 12.合并两个有序链表
- 13.合并K个有序链表
- 14.删除排序数组中的重复项
- 15.搜索旋转排序数组
- 16.字符串相乘
- 17.最大子序和
- 18.全排列
- 19.旋转链表
- 20.不同的路径
- 21.爬楼梯
- 22.子集
- 23.合并两个有序数组
- 24.格雷编码
- 25.二叉树的最大深度
- 26.股票利润I
- 27.股票利润II
- 28.二叉树中的最大路径和
- 29.只出现一次的数字
- 30.环形链表I
- 31.环形链表II
- 32.LRU缓存
- 33.排序链表
- 34.最小栈
- 35.相交链表
- 36.大多数元素
- 37.反转链表
- 38.数组中第k大的数
- 39.存在重复元素
- 40.二叉搜索树中第k小元素
- 41.2的幂
- 42.二叉搜索树的最近公共祖先
- 43.二叉树的最近公共祖先
- 44.删除链表的节点
1.两数相加
解法一:
非递归
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dump = new ListNode(0);
ListNode node = dump;
int carry = 0;
while(l1 != null || l2 != null || carry != 0){
int val1 = l1 != null ? l1.val : 0;
int val2 = l2 != null ? l2.val : 0;
int sum = val1 + val2 + carry;
carry = sum / 10;
node.next = new ListNode(sum % 10);
node = node.next;
if(l1 != null) {
l1 = l1.next;
}
if(l2 != null) {
l2 = l2.next;
}
}
return dump.next;
}
2.寻找两个有序数组的中位数
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m = nums1.length;
int n = nums2.length;
int left = (m + n + 1) / 2;
int right = (m + n + 2) / 2;
return (findKth(nums1, 0, nums2, 0, left) + findKth(nums1, 0, nums2, 0, right)) / 2.0;
}
//i: nums1的起始位置 j: nums2的起始位置
public int findKth(int[] nums1, int i, int[] nums2, int j, int k){
if( i >= nums1.length){
return nums2[j + k - 1];//nums1为空数组
}
if( j >= nums2.length){
return nums1[i + k - 1];//nums2为空数组
}
if(k == 1){
return Math.min(nums1[i], nums2[j]);
}
int midVal1 = (i + k / 2 - 1 < nums1.length) ? nums1[i + k / 2 - 1] : Integer.MAX_VALUE;
int midVal2 = (j + k / 2 - 1 < nums2.length) ? nums2[j + k / 2 - 1] : Integer.MAX_VALUE;
if(midVal1 < midVal2){
return findKth(nums1, i + k / 2, nums2, j , k - k / 2);
}else{
return findKth(nums1, i, nums2, j + k / 2 , k - k / 2);
}
}
3.最长回文子串
解法一:
动态规划:
dp[l][r] = s[l] == s[r] && (dp[l + 1][r - 1] || r - l <= 2)
public String longestPalindrome(String s) {
int len = s.length();
if(len == 0 || len == 1){
return s;
}
//记录最长回文串长度
int longestPalindromeLen = 1;
//记录最长的回文串
String longestPalindrome = s.substring(0,1);
boolean[][] dp = new boolean[len][len];
dp[0][0] = true;
for(int r = 1;r < len;r++){
for(int l = 0;l < r;l++){
if(s.charAt(l) == s.charAt(r) && ((r - l <= 2) || dp[l + 1][r - 1])){
dp[l][r] = true;
if (r - l + 1 > longestPalindromeLen){
longestPalindromeLen = r - l + 1;
longestPalindrome = s.substring(l,r + 1);
}
}
}
}
return longestPalindrome;
}
解法二:
中心扩展法
public String longestPalindrome1(String s) {
if(s.length() == 0 || s.length() == 1){
return s;
}
int max = Integer.MIN_VALUE;
int start = 0;
int end = 0;
for(int i = 0;i < s.length();i++){
int len1 = expandAroundCenter(s,i,i);
int len2 = expandAroundCenter(s,i,i+1);
int len = Math.max(len1,len2);
if(len > end - start){
end = i + len / 2;
start = i - (len - 1) / 2;
}
}
return s.substring(start,end + 1);
}
public int expandAroundCenter(String s,int left,int right){
int l = left;
int r = right;
while(l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)){
r++;
l--;
}
return r - l - 1;
}
4.整数反转
public int reverse(int x) {
if(x < 0){
try {
int a = -x;
String s = String.valueOf(a);
StringBuilder stringBuilder = new StringBuilder(s);
stringBuilder = stringBuilder.reverse();
int res = Integer.parseInt(stringBuilder.toString());
return -res;
}
catch (Exception e){
return 0;
}
}
try {
String s = String.valueOf(x);
StringBuilder stringBuilder = new StringBuilder(s);
stringBuilder = stringBuilder.reverse();
return Integer.parseInt(stringBuilder.toString());
}catch (Exception e){
return 0;
}
}
5.字符串转为整数
def myAtoi(self, s: str) -> int:
return max(min(int(*re.findall('^[\+\-]?\d+', s.lstrip())), 2**31 - 1), -2**31)
6.回文数
public boolean isPalindrome(int x) {
String s = String.valueOf(x);
int l = 0;
int r = s.length() - 1;
while(l < r){
if(s.charAt(l) != s.charAt(r)){
return false;
}
l++;
r--;
}
return true;
}
7.乘最多水的容器
public int maxArea(int[] height) {
if(height.length == 0){
return 0;
}
int max = 0;
int l = 0;
int r = height.length -1;
while(l < r){
int h = Math.min(height[l],height[r]);
max = Math.max(max,h * (r - l));
if(height[l] < height[r]){
l++;
}else{
r--;
}
}
return max;
}
8.最长公共前缀
public String longestCommonPrefix(String[] strs) {
if(strs == null || strs.length == 0){
return "";
}
String str = strs[0];
for(String s : strs){
while(!s.startsWith(str)){
str = str.substring(0,str.length() - 1);
}
}
return str;
}
9.三数之和
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> ls = new ArrayList<>();
for (int i = 0; i < nums.length - 2; i++) {
if (i == 0 || (i > 0 && nums[i] != nums[i - 1])) { // 跳过可能重复的答案
int l = i + 1, r = nums.length - 1, sum = 0 - nums[i];
while (l < r) {
if (nums[l] + nums[r] == sum) {
ls.add(Arrays.asList(nums[i], nums[l], nums[r]));
while (l < r && nums[l] == nums[l + 1]) l++;
while (l < r && nums[r] == nums[r - 1]) r--;
l++;
r--;
} else if (nums[l] + nums[r] < sum) {
while (l < r && nums[l] == nums[l + 1]) l++; // 跳过重复值
l++;
} else {
while (l < r && nums[r] == nums[r - 1]) r--;
r--;
}
}
}
}
return ls;
}
10.最接近三数之和
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int closeThreeNums = nums[0] + nums[1] + nums[2];
for(int i = 0;i < nums.length - 2;i++){
int l = i + 1;
int r = nums.length - 1;
while(l < r) {
int threeNums = nums[l] + nums[r] + nums[i];
if (Math.abs(threeNums - target) < Math.abs(closeThreeNums - target)) {
closeThreeNums = threeNums;
}
if (threeNums > target) {
r--;
} else if (threeNums < target) {
l++;
} else {
return target;
}
}
}
return closeThreeNums;
}
11.有效的括号
public boolean isValid(String s) {
if(s.length() == 0){
return true;
}
Stack<Character> stack = new Stack<>();
for(int i = 0;i < s.length();i++){
if(stack.isEmpty()){
stack.push(s.charAt(i));
}else{
if(isSym(stack.peek(),s.charAt(i))){
stack.pop();
}else{
stack.push(s.charAt(i));
}
}
}
return stack.isEmpty();
}
private boolean isSym(char c1, char c2) {
return (c1 == '(' && c2 == ')') || (c1 == '[' && c2 == ']') || (c1 == '{' && c2 == '}');
}
12.合并两个有序链表
解法一:
非递归
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode dump = new ListNode(-1);
ListNode tmp = dump;
while(l1 != null && l2 != null){
if(l1.val > l2.val){
tmp.next = l2;
tmp = tmp.next;
l2 = l2.next;
}else{
tmp.next = l1;
l1 = l1.next;
tmp = tmp.next;
}
}
if (l1 == null) {
tmp.next = l2;
} else {
tmp.next = l1;
}
return dump.next;
}
解法二:
递归
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) {
return l2;
}
else if (l2 == null) {
return l1;
}
else if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
}
else {
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
}
13.合并K个有序链表
public ListNode mergeKLists(ListNode[] lists) {
if(lists.length == 0){
return null;
}
if(lists.length == 1){
return lists[0];
}
if(lists.length == 2){
return mergeTwoLists(lists[0],lists[1]);
}
int mid = lists.length / 2;
ListNode[] l1 = new ListNode[mid];
for(int i = 0; i < mid;i++){
l1[i] = lists[i];
}
ListNode[] l2 = new ListNode[lists.length - mid];
for(int i = mid,j = 0;i < lists.length && j < i;i++,j++){
l2[j] = lists[i];
}
return mergeTwoLists(mergeKLists(l1),mergeKLists(l2));
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode dump = new ListNode(-1);
ListNode tmp = dump;
while(l1 != null && l2 != null){
if(l1.val > l2.val){
tmp.next = l2;
tmp = tmp.next;
l2 = l2.next;
}else{
tmp.next = l1;
l1 = l1.next;
tmp = tmp.next;
}
}
if(l1 == null){
tmp.next = l2;
}else{
tmp.next = l1;
}
return dump.next;
}
14.删除排序数组中的重复项
public int removeDuplicates(int[] nums) {
int n = 0;
for(int i = 1; i < nums.length; i++){
if(nums[i]!=nums[n]){
n+=1;
nums[n]=nums[i];
}
}
return n+1;
}
15.搜索旋转排序数组
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while(left <= right){
int mid = (left + right) / 2;
if(target == nums[mid]){
return mid;
}
if(nums[left] <= nums[mid]){
//前半部分有序
if(nums[left] <= target && target < nums[mid]){
right = mid - 1;
}else{
left = mid + 1;
}
}else{
if(nums[mid] < target && target <= nums[right]){
left = mid + 1;
}else{
right = mid - 1;
}
}
}
return -1;
}
16.字符串相乘
public String multiply(String num1, String num2) {
if (num1.equals("0") || num2.equals("0")) {
return "0";
}
int[] res = new int[num1.length() + num2.length()];
for (int i = num1.length() - 1; i >= 0; i--) {
int n1 = num1.charAt(i) - '0';
for (int j = num2.length() - 1; j >= 0; j--) {
int n2 = num2.charAt(j) - '0';
int sum = (res[i + j + 1] + n1 * n2);
res[i + j + 1] = sum % 10;
res[i + j] += sum / 10;
}
}
StringBuilder result = new StringBuilder();
for (int i = 0; i < res.length; i++) {
if (i == 0 && res[i] == 0) continue;
result.append(res[i]);
}
return result.toString();
}
17.最大子序和
public int maxSubArray(int[] nums) {
if(nums.length == 0){
return 0;
}
int[] dp = new int[nums.length];
dp[0] = nums[0];
int max = nums[0];
for(int i = 1;i < nums.length;i++){
dp[i] = Math.max(dp[i - 1] + nums[i],nums[i]);
max = Math.max(max,dp[i]);
}
return max;
}
18.全排列
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> permute(int[] nums) {
backtrack(nums,new ArrayList<>(),new int[nums.length]);
return res;
}
private void backtrack(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;
}
tmp.add(nums[i]);
visited[i] = 1;
backtrack(nums,tmp,visited);
tmp.remove(tmp.size() - 1);
visited[i] = 0;
}
19.旋转链表
public ListNode rotateRight(ListNode head, int k) {
if(head==null||k==0){
return head;
}
int len = 1;
ListNode cur = head;
while(cur.next != null){
len++;
cur = cur.next;
}
ListNode tail = cur;
cur.next = head;
cur = head;
int j = k % len;
for(int i = 0;i < len - j;i++){
cur = cur.next;
tail = tail.next;
}
tail.next = null;
return cur;
}
20.不同的路径
public int uniquePaths(int m, int n) {
int[][] dp = new int[m][n];
for(int i = 0;i < m;i++){
for(int j = 0;j < n;j++){
if(i == 0 || j == 0){
dp[i][j] = 1;
}else {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
}
return dp[m-1][n-1];
}
21.爬楼梯
public int climbStairs(int n) {
if(n == 0){
return 1;
}
if(n == 1){
return 1;
}
if(n == 2){
return 2;
}
int[] dp = new int[n+1];
dp[0] = 1;
dp[1] = 1;
dp[2] = 2;
for(int i = 2;i <= n;i++){
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}![在这里插入图片描述](https://img-blog.csdnimg.cn/20200131172135289.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MTkyMjI4OQ==,size_16,color_FFFFFF,t_70)
22.子集
private ArrayList<List<Integer>> result;
public List<List<Integer>> subsets(int[] nums) {
result = new ArrayList<>();
if (nums == null || nums.length == 0) {
return result;
}
List<Integer> list = new ArrayList<>();
generate(0, nums, list);
return result;
}
private void generate(int start, int[] nums, List<Integer> list) {
result.add(new ArrayList<>(list));
for(int i = start;i < nums.length;i++){
list.add(nums[i]);
generate(i + 1,nums,list);
list.remove(list.size() - 1);
}
}
23.合并两个有序数组
public void merge(int[] nums1, int m, int[] nums2, int n) {
for(int i = m,j = 0;i < m + n && j < n;i++,j++){
nums1[i] = nums2[j];
}
Arrays.sort(nums1);
}
24.格雷编码
public List<Integer> grayCode(int n) {
List<Integer> ret = new ArrayList<>();
for(int i = 0; i < 1<<n; ++i)
ret.add(i ^ i>>1);
return ret;
}
25.二叉树的最大深度
public int maxDepth(TreeNode root) {
if(root == null){
return 0;
}
return Math.max(maxDepth(root.left),maxDepth(root.right) )+ 1;
}
26.股票利润I
public int maxProfit(int[] prices) {
if(prices.length == 0){
return 0;
}
int max = Integer.MIN_VALUE;
int min = prices[0];
for(int i : prices){
min = Math.min(min,i);
max = Math.max(i - min,max);
}
return max;
}
27.股票利润II
public int maxProfit(int[] prices) {
if(prices.length == 0){
return 0;
}
int[][] dp = new int[prices.length][2];
int res = 0;
dp[0][0] = 0;
dp[0][1] = -prices[0];
for(int i = 1;i < prices.length;i++){
dp[i][1] = Math.max(dp[i - 1][1],dp[i - 1][0] - prices[i]);
dp[i][0] = Math.max(dp[i - 1][0],dp[i - 1][1] + prices[i]);
res = Math.max(res,Math.max(dp[i][0],dp[i][1]));
}
return res;
}
28.二叉树中的最大路径和
private int res = Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
getMax(root);
return res;
}
private int getMax(TreeNode root) {
if(root == null){
return 0;
}
// a
// b c
int left = Math.max(getMax(root.left),0);//左子树值
int right = Math.max(getMax(root.right),0);//右子树值
res = Math.max(res,root.val + left + right);//a+b+c
return root.val + Math.max(left,right);//a父+a+b / a父+a+c
}
29.只出现一次的数字
异或:
- 相同的数异或得0,不同的数异或得1
- 任何数和0异或都得本身
- 异或同一个数两次,原数不变。
public int singleNumber(int[] nums) {
int len = nums.length;
int result=0;
for(int i=0;i<len;i++){
result ^=nums[i];
}
return result;
}
30.环形链表I
解法一:
public boolean hasCycle(ListNode head) {
if(head == null || head.next == null || head.next.next == null){
return false;
}
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(slow == fast){
return true;
}
}
return false;
}
解法二:
public boolean hasCycle(ListNode head) {
Set<ListNode> nodesSeen = new HashSet<>();
while (head != null) {
if (nodesSeen.contains(head)) {
return true;
} else {
nodesSeen.add(head);
}
head = head.next;
}
return false;
}
31.环形链表II
解法一:
public ListNode detectCycle(ListNode head) {
if(head == null || head.next == null){
return null;
}
ListNode fast = head;
ListNode slow = head;
boolean hasCycle = false;
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
if(slow == fast){
hasCycle = true;
break;
}
}
if(hasCycle){
ListNode node = head;
while(slow != node){
slow = slow.next;
node = node.next;
}
return node;
}else{
return null;
}
}
解法二:
public ListNode detectCycle(ListNode head) {
Set<ListNode> nodesSeen = new HashSet<>();
while (head != null) {
if (nodesSeen.contains(head)) {
return head;
} else {
nodesSeen.add(head);
}
head = head.next;
}
return null;
}
32.LRU缓存
public class LRUCache extends LinkedHashMap<Integer, Integer> {
private int capacity;
public LRUCache(int capacity) {
super(capacity, 0.75F, true);
this.capacity = capacity;
}
public int get(int key) {
return super.getOrDefault(key, -1);
}
public void put(int key, int value) {
super.put(key, value);
}
@Override
protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
return size() > capacity;
}
}
33.排序链表
public ListNode sortList(ListNode head) {
if(head == null){
return head;
}
List<Integer> list = new ArrayList<>();
ListNode cur = head;
while(cur != null){
list.add(cur.val);
cur = cur.next;
}
Collections.sort(list);
ListNode dump = new ListNode(-1);
ListNode newHead = dump;
for(int i = 0; i < list.size();i++){
newHead.next = new ListNode(list.get(i));
newHead = newHead.next;
}
return dump.next;
}
34.最小栈
class MinStack {
/** initialize your data structure here. */
int min = Integer.MAX_VALUE;
Stack<Integer> stack;
public MinStack() {
stack = new Stack<>();
}
public void push(int x) {
if(x <= min){
stack.push(min);
min = x;
}
stack.push(x);
}
public void pop() {
if (stack.pop() == min) {
min = stack.pop();
}
}
public int top() {
return stack.peek();
}
public int getMin() {
return min;
}
}
35.相交链表
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int aLen = 0;
ListNode a = headA;
while(a != null){
aLen++;
a = a.next;
}
int bLen = 0;
ListNode b = headB;
while(b != null){
bLen++;
b = b.next;
}
int k = Math.abs(aLen - bLen);
if(aLen > bLen){
for(int i = 0; i < k;i++) {
headA = headA.next;
}
}else if(aLen < bLen){
for(int i = 0; i < k;i++) {
headB = headB.next;
}
}
while(headA != headB){
headA = headA.next;
headB = headB.next;
}
return headA;
}
36.大多数元素
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length / 2];
}
37.反转链表
解法一:
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
解法二:
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode pre = null;
ListNode cur = head;
while(cur != null){
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
38.数组中第k大的数
public int findKthLargest(int[] nums, int k) {
Arrays.sort(nums);
return nums[nums.length - k];
}
39.存在重复元素
public boolean containsDuplicate(int[] nums) {
Set<Integer> set = new HashSet<>();
for(int i : nums){
if(set.contains(i)){
return true;
}
set.add(i);
}
return false;
}
40.二叉搜索树中第k小元素
List<Integer> res = new ArrayList<>();
public int kthSmallest(TreeNode root, int k) {
dfs(root,res);
Collections.sort(res);
return res.get(k-1);
}
public void dfs(TreeNode root,List<Integer> list){
if(root == null){
return;
}
dfs(root.left,list);
list.add(root.val);
dfs(root.right,list);
}
41.2的幂
正数原码和取反后的补码相与再和原数比较
public boolean isPowerOfTwo(int n) {
return (n > 0) && (n & -n) == n;
}
42.二叉搜索树的最近公共祖先
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
return lca(root, p, q);
}
public TreeNode lca(TreeNode root, TreeNode p, TreeNode q){
if((root.val - p.val) * (root.val - q.val) <= 0){
return root;
}else if(root.val < p.val && root.val < q.val){
return lca(root.right,p,q);
}else{
return lca(root.left,p,q);
}
}
43.二叉树的最近公共祖先
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null){
return null;
}
if(root == p || root == q){
return root;
}
TreeNode left = lowestCommonAncestor(root.left,p,q);
TreeNode right = lowestCommonAncestor(root.right,p,q);
if(left != null && right != null){
return root;
}else if(left != null){
return left;
}else{
return right;
}
}
44.删除链表的节点
public void deleteNode(ListNode node) {
node.val = node.next.val;
node.next = node.next.next;
}