括号序列
import java.util.*;
public class Solution {
/**
*
* @param s string字符串
* @return bool布尔型
*/
public boolean isValid (String s) {
// write code here
Stack<Character> stack=new Stack<>();
for(char ch:s.toCharArray()) //字符串转为字符数组
{
if(ch=='(')
stack.push(')');
else if(ch=='[')
stack.push(']');
else if(ch=='{')
stack.push('}');
//如果栈为空,就不会执行右边语句,因此不用担心空栈pop
//到这一步,说明符号为),],},因此若栈为空,或者没有与之相等的,那么这个括号必然无法正确匹配成功
else if(stack.empty() || stack.pop()!=ch)
return false;
}
return stack.empty(); //栈空返回true,不是说运行完出来了就代表正常匹配了,有可能是(((())),这样就是不匹配的
}
}
用两个栈实现队列
import java.util.Stack;
public class Solution {
//将stack1的栈顶作为队列的尾部,将stack2的栈顶作为队列的头部
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
//push正常进行
public void push(int node) {
stack1.push(node);
}
//pop时,将stack1的全部元素转到stack2中,这样原来stack1中栈底的元素就跑到stack2栈顶,这样就实现了队列先进先出的功能
//同时注意要将stack1恢复原样,这里只是将stack2作为一个中转站,元素真正还是保存在stack1中
public int pop() {
while(!stack1.empty())
{
stack2.push(stack1.pop());
}
int ans=stack2.pop();
while(!stack2.empty())
{
stack1.push(stack2.pop());
}
return ans;
}
}
class CQueue {
LinkedList<Integer> stack1;
LinkedList<Integer> stack2;
public CQueue() {
stack1=new LinkedList<Integer>();
stack2=new LinkedList<Integer>();
}
public void appendTail(int value) {
stack1.add(value);
}
public int deleteHead() {
while(!stack1.isEmpty())
{
stack2.add(stack1.pop());
}
int ans=-1;
if(!stack2.isEmpty())
{
ans=stack2.pop();
}
return ans;
}
}
/**
* Your CQueue object will be instantiated and called as such:
* CQueue obj = new CQueue();
* obj.appendTail(value);
* int param_2 = obj.deleteHead();
*/
二分查找思路:
1、首先确定数组中间的下标
mid=(left+right)/2;
2、然后让需要查找的数findVal和arr[mid]进行比较
①如果findVal>arr[mid],说明要查找的数在mid右边,因此需要递归地向右查找
②如果findVal
结束递归条件:
1、找到则结束
2、递归完整个数组仍未找到findVal,结束递归。即left>right。
二分查找(含重复数字,返回第一次出现位置)
先正常进行二分查找的步骤,然后当返回位置到主程序时,对第一次出现的位置再进行处理。
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
int position=binarySearch(nums,0,nums.length-1,target);
if(position<=0)
return position;
else
{
int tmp=position;
while(--tmp>=0 && nums[tmp]==target)
{
continue;
}
position=tmp+1;
}
return position;
}
public static int binarySearch(int arr[],int left,int right,int target)
{
if(left>right)
return -1;
int mid=(left+right)/2;
if(target==arr[mid])
return mid;
if(target<arr[mid])
return binarySearch(arr,left,mid-1,target);
else
return binarySearch(arr,mid+1,right,target);
}
}
链表中环的入口节点
题意
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
解题思路
入口节点即遍历过程第一个再次到达的节点。
第一步:确定链表中包含环
方法:两个指针同时从头节点出发,一个每次一步,一个每次两步。如果走的快的指针追上了走的慢的,说明有环。如果走的快的指针走到了链表尾,那么说明没环。
第二步:找到环中的节点数
方法:因为上述两个节点相遇的节点一定在环中,所以从这个节点出发,再次走到这个节点,即可计算出环中的节点数。
第三步:找到链表中环的入口节点
方法:两个指针从链表头节点出发,一个先走环的节点数步,然后两个指针同时往前走,两个指针相遇的节点即是环的入口节点。
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
//先判断是否存在环
if(isCircle(head)==false)
return null;
else
{
//存在环,判断环的节点个数
ListNode meetNode=getMeetNode(head);
ListNode fast=meetNode;
ListNode slow=meetNode;
int count=1; //保存环的节点个数
while(fast.next!=slow)
{
fast=fast.next;
count++;
}
//已得到环的节点个数后
//将两个指针指向第一个节点,然后让一个节点先走环的节点数n
fast=head;
slow=head;
while(count-->0)
{
fast=fast.next;
}
while(fast!=slow)
{
fast=fast.next;
slow=slow.next;
}
return fast;
}
}
public boolean isCircle(ListNode head)
{
ListNode tmp=head;
ListNode fast=tmp;
ListNode slow=tmp;
while(fast!=null && fast.next!=null)
{
fast=fast.next.next;
slow=slow.next;
if(slow==fast)
{
return true;
}
}
return false;
}
public ListNode getMeetNode(ListNode head)
{
ListNode tmp=head;
ListNode fast=tmp;
ListNode slow=tmp;
while(true)
{ fast=fast.next.next;
slow=slow.next;
if(slow==fast)
{
return fast;
}
}
}
}
二叉树深度
递归实现
结束条件为当前节点为空,则返回0
否则向左子树和右子树递归。
每次递归返回两者最大值+1
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int maxDepth(TreeNode root) {
if(root==null)
return 0;
int leftLen=maxDepth(root.left);
int rightLen=maxDepth(root.right);
return 1+Math.max(leftLen,rightLen);
}
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
//List> res=new ArrayList>();
//这么定义是错误的
List<List<Integer>> res=new ArrayList<>();
//注意!!是Deque
Queue<TreeNode> queue=new ArrayDeque<>();
if(root==null)
return res;
//return queue;
queue.add(root);
//List> res=new ArrayList>();
//不能在这里定义res,因为上面要返回List>而不是queue
while(!queue.isEmpty())
{
int n=queue.size();
List<Integer> list=new ArrayList<>();
for(int i=0;i<n;i++)
{
TreeNode node=queue.poll();
list.add(node.val);
if(node.left!=null)
{
//不是root,queue.poll得到的是node
//queue.add(root.left);
queue.add(node.left);
}
if(node.right!=null)
{
//queue.add(root.right);
queue.add(node.right);
}
}
res.add(list);
}
return res;
}
}
左转字符串
要点:获取字符串的子串函数是
substring(int begin,int end);(左闭右开)
String str=new String("HelloWorld");
String sub=str.substring(0,5); //sub="Hello"
class Solution {
public String reverseLeftWords(String s, int n) {
String sub1=s.substring(0,n);
String sub2=s.substring(n,s.length());
return sub2+sub1;
}
}
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @return string字符串
*/
public String replaceSpace (String s) {
// write code here
StringBuffer sb=new StringBuffer();
char chArr[]=s.toCharArray();
for(int i=0;i<s.length();i++)
{
if(chArr[i]!=' ')
{
sb.append(chArr[i]);
}
else
{
sb.append("%20");
}
}
return sb.toString();
}
}
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode ReverseList(ListNode head) {
if(head==null || head.next==null)
return head;
//一直遍历到最后一个节点,在其递归返回的过程中改变相邻节点的指向关系
//node是最后返回要的头节点
ListNode node=ReverseList(head.next);
//改变指向关系
head.next.next=head;
head.next=null;
return node;
}
}
最长无重复子串
import java.util.*;
public class Solution {
/**
*
* @param arr int整型一维数组 the array
* @return int整型
*/
/*
思路:先记录已经统计的子串的长度,直到遇到有重复的字串,则将由头到此处的元素全部删除,
重新计数,最后结果取最大的付给返回结果res
*/
public int maxLength (int[] arr) {
// write code here
if(arr.length<=1)
return arr.length;
int res=0;
ArrayList<Integer> list=new ArrayList<>();
list.add(arr[0]);
for(int i=1;i<arr.length;i++)
{
if(list.contains(arr[i]))
{
int p=list.indexOf(arr[i]);
while(p>=0)
{
list.remove(0);
p--;
}
}
list.add(arr[i]);
res=Math.max(list.size(),res);
}
return res;
}
}
斐波那契数列
递归:
public class Solution {
public int Fibonacci(int n) {
if(n<=1)
return n;
return Fibonacci(n-1)+Fibonacci(n-2);
}
}
利用数组:
public class Solution {
public int Fibonacci(int n) {
if(n<=1)
return n;
int arr[]=new int[40];
arr[0]=0;
arr[1]=1;
int i;
for(i=2;i<=n;i++)
{
arr[i]=arr[i-1]+arr[i-2];
}
return arr[n];
}
}
不借助数组:
public class Solution {
public int Fibonacci(int n) {
if(n<=1)
return n;
int i=2;
int value1=0,value2=1,res=0;
while(i++<=n)
{
res=value1+value2;
value1=value2;
value2=res;
}
return res;
}
}
最小的k个数
由于只用选出最小的k个数,因此不用完全排序。可以使用选择排序,只要选出了k个以后即可退出循环
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> list=new ArrayList<>();
if(input.length<k)
return list;
int count=0;
int i=0;
int position=0;
while(count<k && i<input.length)
{
//采用选择排序,每次找出一个最小的
int minNum=input[position],minPosition=position;
int j;
for(j=position;j<input.length;j++)
{
if(minNum>input[j])
{
minNum=input[j];
minPosition=j;
}
}
input[minPosition]=input[position];
//input[position]=minNum;
list.add(minNum);
count++;
position++;
}
return list;
}
}
合并两个有序数组
由后往前进行遍历,较大的数先插入即可
由于是将B的数插入到A中,因此遍历结束后如果是A数组有剩余,也无需做什么,如果是B数组有剩余,则还需要将B数组中的元素移到A中
public class Solution {
public void merge(int A[], int m, int B[], int n) {
int i=m-1,j=n-1;
int p=A.length-1;
while(i>=0 && j>=0)
{
if(A[i]<B[j])
{
A[p--]=B[j--];
}
else
{
A[p--]=A[i--];
}
}
while(j>=0)
{
A[p--]=B[j--];
}
}
}
剑指 Offer 52. 两个链表的第一个公共节点
思路:两个链表长度分别为L1+C、L2+C, C为公共部分的长度,做法: 第一个人走了L1+C步后,回到第二个人起点走L2步;第2个人走了L2+C步后,回到第一个人起点走L1步。 当两个人走的步数都为L1+L2+C时就两个家伙就相爱了
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode node1=headA;
ListNode node2=headB;
while(node1!=node2)
{
node1=node1==null?headB:node1.next;
node2=node2==null?headA:node2.next;
}
return node1;
}
}