@[toc]
数组
1299. 将每个元素替换为右侧最大元素
题目 思路: 逆序解决,而且不能用多余的空间, arr[i] = max(arr[i+1],res[i+1])
import java.util.Map;
import java.util.Scanner;
public class Solution {
public int[] replaceElements(int[] arr){
int cur_max = arr[arr.length-1];
arr[arr.length-1] = -1;
for(int i = arr.length-2;i >=0;i--){
int tmp = arr[i];
arr[i] = Math.max(cur_max,arr[i+1]);
cur_max = tmp;
}
return arr;
}
public static void main(String[] args){
Solution test = new Solution();
Scanner sc = new Scanner(System.in);
String[] nums = null;
nums = sc.nextLine().split(" ");
int[] arr = new int[nums.length];
for(int i = 0;i < nums.length;i++){
arr[i] = Integer.valueOf(nums[i]);
}
int[] res = test.replaceElements(arr);
for(int i:res){
System.out.print(i+" ");
}
}
}
42.接雨水
题目 思路: 记录该位置左边的最大值和右边的最大值,然后该位置接水量就是Math.min(right[i],left[i]) - height[i]
import java.util.Scanner;
public class Solution {
public int trap(int[] height){
if (height.length < 3){
return 0;
}
int[] right = new int[height.length];
int[] left = new int[height.length];
left[0] = height[0];
right[height.length - 1] = height[height.length - 1];
for(int i = 1;i<height.length;i++){
left[i] = Math.max(height[i],left[i-1]);
}
for(int i = height.length - 2 ;i >= 0;i--){
right[i] = Math.max(height[i],right[i+1]);
}
int res = 0;
for(int i = 0;i < height.length;i++){
res += Math.min(right[i],left[i]) - height[i];
}
return res;
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String[] nums = null;
nums = sc.nextLine().split(" ");
int[] height = new int[nums.length];
for(int i=0;i<nums.length;i++){
height[i] = Integer.valueOf(nums[i]);
}
Solution test = new Solution();
System.out.println(test.trap(height));
}
}
双指针
三数之和
题目 思路: 排序后,用双指针 注意: 1、排除重复答案的
if(i > 0 && nums[i] == nums[i-1]){
continue;
}
2、判断tmp==0后不能直接left++ right--
while(left < right && nums[left] == nums[left+1]){
left += 1;
}
while(left < right && nums[right] == nums[right - 1]){
right -= 1;
}
import java.lang.reflect.Array;
import java.util.*;
public class Solution {
public List<List<Integer>> threeSum(int[] nums){
List<List<Integer>> res = new ArrayList<List<Integer>>();
if(nums.length < 3){
return res;
}
Arrays.sort(nums);
for(int i = 0;i<nums.length-2;i++){
// 处理 答案重复
if(i > 0 && nums[i] == nums[i-1]){
continue;
}
int left = i + 1;
int right = nums.length - 1;
while(left < right){
int tmp = nums[i] + nums[left] + nums[right];
if (tmp == 0){
List<Integer> cur = new ArrayList<>();
cur.add(nums[i]);
cur.add(nums[left]);
cur.add(nums[right]);
res.add(cur);
while(left < right && nums[left] == nums[left+1]){
left += 1;
}
while(left < right && nums[right] == nums[right - 1]){
right -= 1;
}
left += 1;
right -=1;
}
else if(tmp > 0){
right -= 1;
}
else{
left += 1;
}
}
}
return res;
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String[] arr = null;
arr = sc.nextLine().split(" ");
int[] nums = new int[arr.length];
for(int i = 0;i < arr.length;i++){
nums[i] = Integer.valueOf(arr[i]);
}
Solution test = new Solution();
System.out.println(test.threeSum(nums));
}
}
链表
206.反转链表
public class Solution {
public ListNode reverseList(ListNode head){
ListNode pre = null;
ListNode cur = head;
while(head != null){
cur = head;
head = head.next; //注意把提前这一行放这里
cur.next = pre;
pre = cur;
}
return cur;
}
public static void main(String[] args) {
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(5);
Solution test = new Solution();
ListNode res = test.reverseList(head);
while(res != null){
System.out.print(res.val + " ");
res = res.next;
}
}
}
反转链表2
题目 思路 第一步:找到待反转节点的前一个节点。记录为beforInverNode,并记录开始反转的节点startInverNode 第二步:反转m到n这部分。 第三步:将反转的起点的next指向反转的后面一部分。 第四部:将startInverNode的next指向后面不需要反转的部分 注意反转完后链表的状态: 所以需要:
beforeInverseNode.next = pre;
startInverseNode.next = node;
import java.util.List;
public class Solution {
public ListNode reverseBetween(ListNode head,int m,int n){
ListNode res = new ListNode(0);
res.next = head;
ListNode node = res;
for(int i = 1;i < m;i++){
node = node.next;
}
ListNode beforeInverseNode = node;
node = node.next;
ListNode startNode = node;
ListNode pre = null;
ListNode cur = null;
for(int i = m;i <=n;i++){
cur = node;
node = node.next;
cur.next = pre;
pre = cur;
}
beforeInverseNode.next = pre;
startNode.next = node;
return res.next;
}
public static void main(String[] args) {
int m = 2, n = 6;
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
head.next.next.next.next = new ListNode(5);
head.next.next.next.next.next = new ListNode(6);
head.next.next.next.next.next.next = new ListNode(7);
Solution test = new Solution();
ListNode res = test.reverseBetween(head,m,n);
while(res != null){
System.out.print(res.val + " ");
res = res.next;
}
}
}
k个一组翻转链表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode res = new ListNode(0);
res.next = head;
ListNode lastNode = res;
while(head != null){
ListNode startNode = head;
int count = 0;
ListNode headd = null;
while(head != null && count <k){
count ++;
if(count == k){
headd = head;
}
head = head.next;
}
if(headd != null){
headd.next = null;
}
if(count == k){
ListNode endNode = reverse(startNode);
lastNode.next = endNode;
lastNode = startNode;
}
else{
lastNode.next = startNode;
}
}
return res.next;
}
public ListNode reverse(ListNode head){
ListNode pre = null;
ListNode cur = head;
while (head != null){
head = head.next;
cur.next = pre;
pre = cur;
cur = head;
}
return pre;
}
}
21.合并两个有序链表
题目 递归
public class Solution {
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;
}
}
public static void main(String[] args) {
ListNode l1 = new ListNode(1);
l1.next = new ListNode(2);
l1.next.next = new ListNode(4);
ListNode l2 = new ListNode(1);
l2.next = new ListNode(3);
l2.next.next = new ListNode(4);
Solution test = new Solution();
ListNode res = test.mergeTwoLists(l1,l2);
while(res != null){
System.out.print(res.val + " ");
res = res.next;
}
}
}
23.合并k个排序链表
题目 思路: 分治,两两合并
public class Solution {
public ListNode mergeKlists(ListNode[] lists){
int interval = 1;
int len = lists.length;
while(len > interval){
for(int i = 0;i < len - interval; i += interval * 2){
lists[i] = merge2lists(lists[i], lists[i + interval]);
}
interval *= 2;
}
return len > 0 ? lists[0]:null;
}
public ListNode merge2lists(ListNode l1,ListNode l2){
if(l1 == null){
return l2;
}
else if(l2 == null){
return l1;
}
else if(l1.val < l2.val){
l1.next = merge2lists(l1.next,l2);
return l1;
}
else{
l2.next = merge2lists(l1,l2.next);
return l2;
}
}
public static void main(String[] args) {
// ListNode l1 = new ListNode(1);
// l1.next = new ListNode(4);
// l1.next.next = new ListNode(5);
//
// ListNode l2 = new ListNode(1);
// l2.next = new ListNode(3);
// l2.next.next = new ListNode(4);
//
// ListNode l3 = new ListNode(2);
// l3.next = new ListNode(6);
// ListNode[] lists = {l1,l2,l3};
ListNode[] lists = {};
Solution test = new Solution();
ListNode res = test.mergeKlists(lists);
while(res != null){
System.out.print(res.val + " ");
res = res.next;
}
}
}