滑动窗口+哈希表
import java.util.*;
public class Solution {
/**
*
* @param arr int整型一维数组 the array
* @return int整型
*/
public int maxLength (int[] arr) {
// write code here
int l =0, r;
int max = -1;
HashMap<Integer,Integer> map = new HashMap<>();
for( r = 0;r < arr.length;r++){
//如果哈希表里有与最右边相同的数,把左边界依次右移,删除左边界的数,直到删除相同的数
while(map.containsKey(arr[r])&l<=r){
map.remove(arr[l]);
l++;
}
//注意要先寻找哈希值,再加入哈希表
map.put(arr[r],1);
max = Math.max(max,r-l+1);
}
return max;
}
}
经典斐波拉契数列
public class Solution {
public int jumpFloor(int target) {
//低一步,低两步
int less1=2,less2=1,res=0;
if(target==1||target==2)return target;
for(int i = 3 ;i<=target;i++){
res = less1 +less2;
less2 = less1;
less1 = res;
}
return res;
}
}
一开始想用排列组合写的,但只能过一半的测试用例,大概是30左右就会溢出
public class Solution {
public int jumpFloor(int target) {
if(target == 0)return 0;
//x两步,y一步
int x,y;
int sum = 0;
for(x=0;x*2<=target;x++){
y=target-x*2;
//获取某种组合所有走法,C(y,x+y)
sum += get(y,x+y);
}
return sum;
}
private int get(int a,int b){
int res = 1;
for(int i = 1 ;i<=a; i++,b--){
res = res*b/i;
}
return res;
}
}
用双哈希表写了一个,测试用例过了7/17,有空再写链表
import java.util.*;
public class Solution {
/**
* lru design
* @param operators int整型二维数组 the ops
* @param k int整型 the k
* @return int整型一维数组
*/
public int[] LRU (int[][] arr, int k) {
// write code here
int len =(int) Arrays.stream(arr).filter(x->x[0] == 2).count();
int[] a = new int[len];
int j =0;
//存放数值
HashMap<Integer,Integer> mapx =new HashMap<>();
//存放频繁度,1为最频繁
HashMap<Integer,Integer> mapy =new HashMap<>();
for(int i = 0;i<arr.length ;i++){
if(arr[i][0]==1){
mapx.put(arr[i][1],arr[i][2]);
Set<Integer> keys = mapy.keySet();
for(Integer key : keys){
if(mapy.get(key)==k){
mapx.remove(key);
// mapy.remove(key);
}
mapy.put(key,mapy.get(key)+1);
}
mapy.put(arr[i][1],1);
}else if((arr[i][0]==2)){
int x=arr[i][1];
if(mapx.containsKey(x)&&mapy.get(x)<=k){
int flag = mapy.get(x);
Set<Integer> keys = mapy.keySet();
for(Integer key : keys){
if(mapy.get(key)<flag){
mapy.put(key,mapy.get(key)+1);
}
}
mapy.put(x,1);
a[j++]=mapx.get(x);
}else{
a[j++]=-1;
}
}
}
return a;
}
}
import java.util.*;
public class Solution {
/**
* lru design
* @param operators int整型二维数组 the ops
* @param k int整型 the k
* @return int整型一维数组
*/
public int[] LRU (int[][] operators, int k) {
// write code here
Map<Integer, Integer> map = new LinkedHashMap<>();
List<Integer> list = new LinkedList<>();
for (int[] operator : operators) {
int key = operator[1];
switch(operator[0]) {
case 1:
int value = operator[2];
if (map.size() < k) {
map.put(key, value);
} else {
Iterator it = map.keySet().iterator();
map.remove(it.next());
map.put(key, value);
}
break;
case 2:
if (map.containsKey(key)) {
int val = map.get(key);
list.add(val);
map.remove(key);
map.put(key, val);
} else {
list.add(-1);
}
break;
default:
}
}
int[] res = new int[list.size()];
int i = 0;
for (int val : list) {
res[i++] = val;
}
return res;
}
}
import java.util.Stack;
public class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node);
}
public int pop() {
//若stack2为空,吧stack1的元素全部入栈到stack2
if(stack2.empty()){
while(!stack1.empty()){
stack2.push(stack1.pop());
}
}
return stack2.pop();
}
}
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 如果目标值存在返回下标,否则返回 -1
* @param nums int整型一维数组
* @param target int整型
* @return int整型
*/
public int search (int[] nums, int target) {
// write code here
if (nums == null || nums.length == 0)return -1;
int l = 0,r =nums.length-1;
int res = search1(l,r,nums,target);
//这里一定要先判断res>0,不然会出现越界
while(res>0&&nums[res-1]==target)res--;
return res;
}
private int search1(int l,int r,int[] nums,int tar){
while(l<=r){
int m =(l+r)/2;
if(nums[m]==tar)return m;
if(nums[m]>tar){
r=m-1;
}else{
l=m+1;
}
}
return -1;
}
}
队列方法:
添加元素到队尾:add() 、offer();队列满时前者抛出一个 unchecked 异常,后者返回false
删除队首元素并返回:remove()、 poll();队列空时前者抛出异常,后者返回null
查询队首元素:element()、peek(); 队列空时前者抛出异常,后者返回null
Root = [1 , 2 , 3 , # , 4 , 5 , # , 6 ]
N = 1
Queue = [ 1 ] → [ 1 , 2 ] → [ 1 , 2 , 3 ] → [ 2 , 3 ]
Level = [ 1 ]
Res = [ 1 ]
N = 2
Queue = [ 2 , 3 ] → [ 2 , 3 ] → [ 2 , 3 , 4 ] → [ 3 , 4 ]
Level = [ 2 ]
Queue = [ 3 , 4 ] → [ 3 , 4 , 5 ] → [ 3 , 4 , 5 ] → [ 4 , 5 ]
Level = [ 2 , 3 ]
Res = [ [ 1 ] , [ 2 , 3 ] ]
N = 2
Queue = [ 4 , 5 ] → [ 4 , 5 , 6 ] → [ 4 , 5 , 6 ] → [ 5 , 6 ]
Level = [ 4 ]
Queue = [ 5 , 6 ] → [ 5 , 6 ] → [ 5 , 6 ] → [ 6 ]
Level = [ 4 , 5 ]
Res = [ [ 1 ] , [ 2 , 3 ] , [ 4 , 5 ] ]
N = 1
Queue = [ 6 ] → [ 6 ] → [ 6 ] → [ ]
Level = [ 6 ]
Res = [ [ 1 ] , [ 2 , 3 ] , [ 4 , 5 ] , [ 6 ] ]
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* }
*/
public class Solution {
/**
*
* @param root TreeNode类
* @return int整型ArrayList<ArrayList<>>
*/
public ArrayList<ArrayList<Integer>> levelOrder (TreeNode root) {
// write code here
ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
if(root == null)return res;
Queue<TreeNode> queue =new LinkedList<TreeNode>();
//根节点先进入队列
queue.offer(root);
while(!queue.isEmpty()){
//level用于存储某层的所有结点
ArrayList<Integer> level =new ArrayList<Integer>();
//获取当前队列大小,即队列中的结点数量
int n =queue.size();
for(int i = 0;i<n;i++){
//如果结点存在左右子节点,则进入队列,peek()返回队首元素,不删除
if(queue.peek().left != null)queue.offer(queue.peek().left);
if(queue.peek().right != null)queue.offer(queue.peek().right);
//已经寻找子节点的节点(即队首)添加到level中,并出队
level.add(queue.poll().val);
}
//将某层所有结点加入最终列表中
res.add(level);
}
return res;
}
}
快慢指针
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
if(head == null)return false;
ListNode fast=head,slow=head;
while (null!=fast && null!=fast.next)
{
fast = fast.next.next;
slow = slow.next;
if (fast == slow)
return true;
}
return false;
}
}
无脑遍历三次,第一次存父子映射,第二次找o1所有祖先,第三次从下往上找o2祖先,找到最近公共祖先
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* }
*/
public class Solution {
/**
*
* @param root TreeNode类
* @param o1 int整型
* @param o2 int整型
* @return int整型
*/
public int lowestCommonAncestor (TreeNode root, int o1, int o2) {
// write code here
//结点,结点的父亲结点
HashMap<Integer, Integer> map = new HashMap<Integer,Integer>();
Queue<TreeNode> queue =new LinkedList<>();
queue.offer(root);
//val<=100,根节点的父亲结点设置为101即可
map.put(root.val,101);
//按层遍历,直到找到两个目标结点
while(!map.containsKey(o1)||!map.containsKey(o2)){
//查找队首结点的子节点
TreeNode node =queue.poll();
//有左结点则在哈希映射中加入该对父子结点,并把子节点入队
if(node.left!=null){
map.put(node.left.val,node.val);
queue.offer(node.left);
}
if(node.right!=null){
map.put(node.right.val,node.val);
queue.offer(node.right);
}
}
HashSet<Integer> father = new HashSet<>();
//哈希映射里根节点的父亲结点是101
//遍历所有O1的祖先加入到哈希表中
while(o1!=101){
father.add(o1);
o1 = map.get(o1);
}
//从下往上找,第一个找到的共同祖先则是最近的公共祖先
while(!father.contains(o2))o2=map.get(o2);
return o2;
}
}
[ 1 , 3 , -5 , 6 ]
a = 1 , sum = 1 , max = 1;
a = 3 , sum = 4 , max = 4;
a = -5 , sum = -1 , max = 4;
a = 6 , sum = 6 , max = 6;
当遍历到 -5 时,以-5结尾的子数组最大和为-1;
当遍历到 6 时,如果要加上前面的子数组,也就是加上 -5 的子数组最大和,即-1,则此时子数组最大和就是6本身,而不加上前面的子数组。
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
int max = Integer.MIN_VALUE;
//sum表示以当前遍历的数的前一个数作为末尾,能获得的子数组的最大和
int sum = 0;
for(int a : array){
//如果a的前一个数子数组最大和为负数,则将sum改为a,否则为sum+a
sum = sum < 0 ? a : sum + a;
//判断最大和 和 sum的大小
max = Math.max(sum,max);
}
return max;
}
}
本质都是递归入队,区别在于先序:根左右,中序:左根右,后续:左右根
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* }
*/
public class Solution {
/**
*
* @param root TreeNode类 the root of binary tree
* @return int整型二维数组
*/
public int[][] threeOrders (TreeNode root) {
// write code here
//三个列表存储前序、中序、后序遍历的结果
List<Integer> listPre = new ArrayList<>();
List<Integer> listIn = new ArrayList<>();
List<Integer> listPost = new ArrayList<>();
//调用函数计算遍历结果
preOrder(root, listPre);
inOrder(root, listIn);
postOrder(root, listPost);
//存放结果集
int[][] res = new int[3][listPre.size()];
for(int i = 0; i < listIn.size(); i++){
res[0][i] = listPre.get(i);
res[1][i] = listIn.get(i);
res[2][i] = listPost.get(i);
}
return res;
}
// 先序遍历函数
public void preOrder(TreeNode root, List<Integer> list){
if(root == null)return;
//根左右
list.add(root.val);
preOrder(root.left, list);
preOrder(root.right, list);
}
// 中序遍历函数
public void inOrder(TreeNode root, List<Integer> list){
if(root == null)return;
//左根右
inOrder(root.left, list);
list.add(root.val);
inOrder(root.right, list);
}
// 后序遍历函数
public void postOrder(TreeNode root, List<Integer> list){
if(root == null)return;
//左右根
postOrder(root.left, list);
postOrder(root.right, list);
list.add(root.val);
}
}
import java.util.*;
public class Solution {
public int getLongestPalindrome(String A, int n) {
// write code here
if(n==0)return 0;
//回文串有可能为偶数长度也有可能为奇数长度
//奇数情况下
int max = 1;
for(int i = 0;i<n;i++){
int sum = 1;
int left = i ,right = i;
while(left-1>=0&&right+1<n){
left--;
right++;
if(A.charAt(left)==A.charAt(right)){
sum += 2;
max=Math.max(sum,max);
}else{
left = -1;
}
}
}
//偶数情况下,找到相邻两个相同的字符
for(int i =0;i+1<n;i++){
if(A.charAt(i)==A.charAt(i+1)){
int sum = 2 ;
//极端情况,"aa"
max=Math.max(sum,max);
int left = i,right = i +1;
while(left-1>=0&&right+1<n){
left--;
right++;
if(A.charAt(left)==A.charAt(right)){
sum+=2;
max=Math.max(sum,max);
}else{
left = -1;
}
}
}
}
return max;
}
}
import java.util.*;
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ArrayList<ArrayList<Integer> > Print(TreeNode root) {
ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
if(root == null)return res;
Queue<TreeNode> queue =new LinkedList<TreeNode>();
//根节点先进入队列
queue.offer(root);
int flag = 1;
while(!queue.isEmpty()){
//level用于存储某层的所有结点
ArrayList<Integer> level =new ArrayList<Integer>();
//获取当前队列大小,即队列中的结点数量
int n =queue.size();
for(int i = 0;i<n;i++){
//如果结点存在左右子节点,则进入队列,peek()返回队首元素,不删除
if(queue.peek().left != null)queue.offer(queue.peek().left);
if(queue.peek().right != null)queue.offer(queue.peek().right);
//已经寻找子节点的节点(即队首)添加到level中,并出队
level.add(queue.poll().val);
}
//将某层所有结点加入最终列表中
if(flag==-1){
Collections.reverse(level);
}
res.add(level);
flag*=-1;
}
return res;
}
}