leetcode
two pointers
反向双指针
反转字符串344
解:
class Solution {
public char[] reverseString(char[] s) {
int i = 0 ;
int j = s.length -1;
while(i< j){
char temp = s[i];
s[i] = s[j];
s[j] = temp;
i++;
j--;
}
return s;
}
}
盛最多水的容器11
解:
class Solution {
public int maxArea(int[] height) {
int l =0, r =height.length-1, result =0;
// 套用反向公式
while (l<r){
int tempResult = (Math.min(height[l],height[r])*(r-l));
result = Math.max(result,tempResult);
// 如果L 小说明 L+1 ~R 积水可能比L~R积水大
if(height[l]<= height[r]){
l ++;
}else{
r--;
}
}
return result;
}
}
接雨水 42
解:
class Solution {
public int trap(int[] height) {
int l = 0;
int r = height.length-1;
int leftMax =0;
int rightMax =0;
int result =0;
while (l<r){
// 这部分右边比左边大 所以只考虑左边最大值即可
if(height[l]< height[r]){
leftMax = Math.max(leftMax,height[l]);
result = result + (leftMax-height[l]);
l++;
}else{
rightMax = Math.max(rightMax,height[r]);
result = result + (rightMax-height[r]);
r--;
}
}
return result;
}
}
总结
同向双指针
如果想要数据的相对位置保持不变 那就只能用同向
删除有序数组中的重复项26
解:
class Solution {
public int removeDuplicates(int[] nums) {
int i =0;
int j= 0;
while (j<nums.length){
if(i == 0 || nums[j] != nums[i-1]){
nums[i++] = nums[j++];
}else{
j++;
}
}
return i;
}
}
删除有序数组中的重复项 II 80
解:
class Solution {
public int removeDuplicates(int[] nums) {
int len = nums.length;
if(len<=2){
return len;
}
int l =2, r= 2;
while (r <nums.length){
if(nums[r]!= nums[l-2]){
nums[l++] = nums[r++];
}else{
r++;
}
}
return l;
}
}
移动零 283
解:
class Solution {
public void moveZeroes(int[] nums) {
int n = nums.length, left = 0, right = 0;
while (right < n) {
if (nums[right] != 0) {
swap(nums, left, right);
left++;
}
right++;
}
}
public void swap(int[] nums, int left, int right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
}
}
删除字符串中的所有相邻重复项 1047
解:
class Solution {
public String removeDuplicates(String s) {
char [] str = s.toCharArray();
int i=0,j=0;
while(j<str.length){
str[i] = str[j];
if(i>0 && str[i] == str[i-1]){
i--;
}else{
i++;
}
j++;
}
return new String(str,0,i);
}
}
binary search
常用于排好序的array 时间复杂度是 o(logN)
基础二分查找
二分查找 704
class Solution {
public int search(int[] nums, int target) {
int i = 0, j = nums.length -1;
while(i<=j){
int mid = i+(j-i)/2;
if(target == nums[mid] ){
return mid;
}else if(target > nums[mid] ){
i = mid+1;
}else{
j = mid-1;
} }
return -1;
}}
在排序数组中查找元素的第一个和最后一个位置 34
class Solution {
public int[] searchRange(int[] nums, int target) {
int len = nums.length;
if(len == 0){
return new int [] {-1,-1};
}
int fistPosition = findFirstPosition(nums,target);
if(fistPosition == -1){
return new int[] {-1,-1};
}
int lastPosition = findLastPosition(nums,target);
return new int[]{fistPosition,lastPosition};
}
public int findFirstPosition(int[] nums, int target){
int left = 0;
int right = nums.length-1;
//退出这个循环一定是 left = right
while (left < right){
int mid = left+ (right-left)/2;
if (nums[mid] < target ){
left = mid+1;
}else if(nums[mid] == target){
right = mid;
}else if (nums[mid] >target){
right = mid-1;
}
}
if (nums[left] == target){
return left;
}
return -1;
}
public int findLastPosition(int[] nums, int target){
int left = 0;
int right = nums.length-1;
//退出这个循环一定是 left = right
while (left < right){
// 防止出现死循环
int mid = left+ (right-left+1)/2;
if (nums[mid] < target ){
left = mid+1;
}else if(nums[mid] == target){
left = mid;
}else if (nums[mid] >target){
right = mid-1;
}
}
if (nums[left] == target){
return left;
}
return -1;
}
}
查找有序数组中最接近k的值
class Solution {
public int findClosestNumber(int[] nums) {
int i = 0, j = nums.length -1;
while(i< j-1){
int mid = i+(j-i)/2;
if(target > nums[mid] ){
i = mid;
}else{
j = mid;
}
}
//数组会剩下两个数据
if(target > nums[j]){
return nums[j];
}else if(target < nums[i]){
return nums[i];
}
else {
return target-nums[i] >= nums[j]-target ? nums[j]:nums[i];
}
}
}
进阶二分查找
山脉数组的峰顶索引 852
class Solution {
public int peakIndexInMountainArray(int[] arr) {
int left = 0,right = arr.length-1;
while(left<=right){
int mid = left + (right - left)/2;
if(arr[mid]>arr[mid+1]&& arr[mid]>arr[mid-1]){
return mid;
}
if(arr[mid]>arr[mid+1]){
left = mid;
}
else{
right = mid;
}
}
return -1;
}
}
在 D 天内送达包裹的能力 1011
class Solution {
public int shipWithinDays(int[] weights, int days) {
int left = Arrays.stream(weights).max().getAsInt(), right = Arrays.stream(weights).sum();
while (left < right){
int mid = left + (right - left)/2;
int need = 1, currentWeight = 0;
for(int weight:weights){
if(currentWeight + weight > mid){
++need;
currentWeight = 0;
}
currentWeight += weight;
}
if(need <= days){
right = mid;
}else {
left = mid+1;
}
}
return left;
}
}
Linked List
链表中倒数第k个节点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode i = head, j = head;
for(int c = 0 ;c<k ; c++){
j = j.next;
}
while (j != null){
i = i.next;
j = j.next;
}
return i;
}
}
反转链表
// 循环解法
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode currentNode = head;
while(currentNode!= null){
//先把要断开的节点赋值给一个临时变量
ListNode tempNode = currentNode.next;
//改变指针指向
currentNode.next = pre;
// 赋值 pre和 currentNode
pre = currentNode;
currentNode = tempNode;
}
return pre;
}
//递归解法
public ListNode reverseList(ListNode head) {
return reverse(null,head);
}
private static ListNode reverse(ListNode pre,ListNode cur){
if(cur==null) return pre;
ListNode next = cur.next;
cur.next = pre;
return reverse(cur,next);
}
stack
Stack.peek()
peek()函数返回栈顶的元素,但不弹出该栈顶元素。
Stack.pop()
pop()函数返回栈顶的元素,并且将该栈顶元素出栈。
每日温度 739
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
int len = temperatures.length;
//默认元素0
int [] res = new int[temperatures.length];
Deque<Integer> stack = new ArrayDeque<Integer>();
for (int i = 0; i < temperatures.length ; i++ ){
while(!stack.isEmpty() && temperatures[i]> temperatures[stack.peek()] ){
int index = stack.pop();
res[index] = i-index;
}
stack.push(i);
}
return res;
}
}
行星碰撞 735
class Solution {
public int[] asteroidCollision(int[] asteroids) {
Deque<Integer> stack = new ArrayDeque<>();
for(int asteroid : asteroids){
// 无论左边的星球是正是负 他俩都不会相撞
if(asteroid > 0){
stack.push(asteroid);
}else{
// 三种情况 当前数据为负数
// 栈顶元素为正,且比当前元素绝对值小 可能会存在多条这样的数据所以用while
while (!stack.isEmpty()&& stack.peek() > 0 && stack.peek()< -asteroid){
stack.pop();
}
// 栈顶元素为正 且 相加为0
if(!stack.isEmpty()&& stack.peek() == -asteroid){
stack.pop();
}else if(stack.isEmpty() || stack.peek() < 0){
stack.push(asteroid);
}
}
}
int [] res = new int[stack.size()];
for(int i = stack.size()-1; i>=0; i--){
res[i] = stack.pop();
}
return res;
}
}
有效的括号 20
class Solution {
public boolean isValid(String s) {
int n = s.length();
if (n % 2 == 1) {
return false;
}
Map<Character, Character> pairs = new HashMap<Character, Character>();
pairs.put(')', '(');
pairs.put(']', '[');
pairs.put('}', '{');
Deque<Character> stack = new LinkedList<Character>();
for (int i = 0; i < n; i++) {
char ch = s.charAt(i);
if (pairs.containsKey(ch)) {
if (stack.isEmpty() || stack.peek() != pairs.get(ch)) {
return false;
}
stack.pop();
} else {
stack.push(ch);
}
}
return stack.isEmpty();
}
}
heap
数组中的第K个最大元素215
//沙雕解法
class Solution {
public int findKthLargest(int[] nums, int k) {
Arrays.sort(nums);
return nums[nums.length - k];
}
}
//正经解法
class Solution {
public int findKthLargest(int[] nums, int k) {
//初始化定义最小堆
PriorityQueue<Integer> heap = new PriorityQueue<>();
//遍历数组 如果遇到比堆顶大的数字 则加进堆中
for ( int num:nums) {
// 如果不带 = 就是不包含重复数字
if(heap.size()< k || heap.peek() <= num){
//添加元素
heap.offer(num);
}
if(heap.size()>k){
// 拿出堆顶元素
heap.poll();
}
}
return heap.peek();
}
}
合并K个升序链表 23
public static ListNode mergeKLists(ListNode[] lists) {
//创建一个堆,并设置元素的排序方式
PriorityQueue<ListNode> heap = new PriorityQueue<>((a,b)-> a.val-b.val);
//遍历链表数组,然后将每个链表的每个节点都放入堆中
for(int i=0;i<lists.length;i++) {
while(lists[i] != null) {
heap.add(lists[i]);
lists[i] = lists[i].next;
}
}
//初始化一个节点这个值可以是任意数
ListNode head = new ListNode(-1);
//通过一个链表指向原链表地址,赋值完成时,打印原链表的指针地址。获取所有值。 这个是解释 为什么操作的是 head 返回的是 res
ListNode res = head;
//从堆中不断取出元素,并将取出的元素串联起来
while( !heap.isEmpty() ) {
head.next = heap.poll();
head = head.next;
}
head.next = null;
return res.next;
}
HashMap
两数之和
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
for (int i=0;i<nums.length;i++){
if(map.containsKey(target- nums[i])){
return new int[] {map.get(target- nums[i]),i};
}
map.put(nums[i],i);
}
return new int[0];
}
}
和为 K 的子数组
class Solution {
public int subarraySum(int[] nums, int k) {
Map<Integer,Integer> map = new HashMap<>();
map.put(0,1);
int sum = 0 ,res =0;
for (int nu :nums ){
sum += nu;
if(map.containsKey(sum - k)){
res += map.get(sum - k);
}
map.put(sum,map.getOrDefault(sum,0)+1);
}
return res;
}
}
无重复字符的最长子串
移动窗口+HashMap
class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length(), ans = 0;
Map<Character, Integer> map = new HashMap<>();
for (int end = 0, start = 0; end < n; end++) {
char alpha = s.charAt(end);
if (map.containsKey(alpha)) {
start = Math.max(map.get(alpha), start);
}
ans = Math.max(ans, end - start + 1);
map.put(s.charAt(end), end + 1);
}
return ans;
}
}
## search + DP