1. 两数之和
1.这道题目首先想到的是用暴力破解的方法
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] result = new int[2];
// 循环
for(int i=0;i<nums.length-1;i++){
for(int j=i+1;j<nums.length;j++){
if(nums[i]+nums[j]==target){
return new int[]{i,j};
}
}
}
return result;
}
}
2.HashMap方法(本思路为,先将数组遍历存储到Map中,然后,在每次遍历查询的时候去掉自身的数据,这里需要注意的地方是,map.remove(key)是根据key删除,map.remover(key,value))是根据键值对删除。可能存在{3,3}这样的数据,所以删除的话,要用map.remove(key,value),否则,用map.remove(key)的话,会删除两个值。
/*使用存储空间 */
import java.util.Map;
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] result = new int[2];
// 结果
Map<Integer,Integer> map = new HashMap<>();
for(int i=0;i<nums.length;i++){
map.put(nums[i],i);
}
for(int i=0;i<nums.length;i++){
map.remove(nums[i],i);
if(map.containsKey(target-nums[i])){
return new int[]{i,map.get(target-nums[i])};
}
map.put(nums[i],i);
}
return result;
}
}
3.HashMap的优化方法 (Letcode官方解法,先查询后放到Map中)
/*使用存储空间 */
import java.util.Map;
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] result = new int[2];
// 结果
Map<Integer,Integer> map = new HashMap<>();
for(int i=0;i<nums.length;i++){
if(map.containsKey(target-nums[i])){
return new int[]{i,map.get(target-nums[i])};
}
map.put(nums[i],i);
}
return result;
}
}
20. 有效的括号
- 这道题的核心思路是把逻辑梳理清楚
由于栈结构的特殊性,非常适合做对称匹配类的题目。
首先要弄清楚,字符串里的括号不匹配有几种情况。
一些同学,在面试中看到这种题目上来就开始写代码,然后就越写越乱。
建议要写代码之前要分析好有哪几种不匹配的情况,如果不动手之前分析好,写出的代码也会有很多问题。
先来分析一下 这里有三种不匹配的情况,
第一种情况,字符串里左方向的括号多余了 ,所以不匹配。 !括号匹配1
第二种情况,括号没有多余,但是 括号的类型没有匹配上。 !括号匹配2
第三种情况,字符串里右方向的括号多余了,所以不匹配。 !括号匹配3
我们的代码只要覆盖了这三种不匹配的情况,就不会出问题,可以看出 动手之前分析好题目的重要性。
动画如下:
1.常规逻辑
import java.util.Stack;
class Solution {
public boolean isValid(String s) {
// 首先对字符串进行拆分
char[] chars = s.toCharArray();
Stack<Character> stack = new Stack<>();
for(int i=0;i<chars.length;i++){
if(chars[i]=='('||chars[i]=='{'||chars[i]=='['){
stack.push(chars[i]);
}else{
if(stack.isEmpty()||(!isMatch(stack.peek(),chars[i]))){
return false;
}
stack.pop();
}
}
if(stack.isEmpty()){
return true;
}else{
return false;
}
}
public boolean isMatch(char left,char right){
if(left=='('&&right==')'){return true;}
if(left=='{'&&right=='}'){return true;}
if(left=='['&&right==']'){return true;}
return false;
}
}
2.Letcode经典逻辑
import java.util.Stack;
class Solution {
public boolean isValid(String s) {
// 首先对字符串进行拆分
char[] chars = s.toCharArray();
Stack<Character> stack = new Stack<>();
for(int i=0;i<chars.length;i++){
if(chars[i]=='('){
stack.push(')');
}else if(chars[i]=='{'){
stack.push('}');
}else if(chars[i]=='['){
stack.push(']');
}else {
if(stack.isEmpty()){
return false;
}
if(stack.peek()==chars[i]){
stack.pop();
}else{
return false;
}
}
}
if(!stack.isEmpty()){
return false;
}
return true;
}
}
《链表专题》
21. 合并两个有序链表
1.使用类似归并的算法
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
// 首先新建一个链表
ListNode newList = new ListNode(0);
ListNode pre = newList;
if(list1==null){
newList.next = list2;
}
if(list2==null){
newList.next = list1;
}
while(list1!=null&&list2!=null){
if(list1.val<list2.val){
newList.next = list1;
list1 = list1.next;
}else{
newList.next = list2;
list2 = list2.next;
}
newList = newList.next;
}
if(list1!=null){
newList.next = list1;
}
if(list2!=null){
newList.next = list2;
}
return pre.next;
}
}
2.递归方法(核心是递归方程)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if(list1==null){
return list2;
}else if(list2==null){
return list1;
}else if(list1.val>list2.val){
list2.next = mergeTwoLists(list1,list2.next);
return list2;
}else{
list1.next = mergeTwoLists(list1.next,list2);
return list1;
}
}
}
141. 环形链表
1.暴力破解,超级无敌经典的方法
/**
* 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) {
int count = 0;
while(count<100000&&head!=null){
head = head.next;
count++;
}
return count<100000?false:true;
}
}
2.快慢指针
/**
* 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) {
ListNode fast = head;
ListNode slow = head;
while(fast!=null&&fast.next!=null){
fast = fast.next.next;
slow = slow.next;
if(fast==slow){
return true;
}
}
return false;
}
}
3.HashSet特性
/**
* 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) {
Set<ListNode> set = new HashSet<ListNode>();
while(head!=null){
if(!set.add(head)){
return true;
}
head = head.next;
}
return false;
}
}
160. 相交链表
1.经典写法
/**
* 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) {
int countA = 0;
int countB = 0;
ListNode a = headA;
ListNode b = headB;
while(a!=null){
countA++;
a = a.next;
}
while(b!=null){
countB++;
b = b.next;
}
int result = Math.abs(countA-countB);
if(countA>countB){
for(int i=0;i<result;i++){
headA = headA.next;
}
}
if(countA<countB){
for(int i=0;i<result;i++){
headB = headB.next;
}
}
while(headA!=null&&headB!=null){
if(headB==headA){
return headA;
}
headA = headA.next;
headB = headB.next;
}
return null;
}
}
2.使用Set集合
/**
* 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) {
Set<ListNode> set = new HashSet<ListNode>();
while(headA!=null){
set.add(headA);
headA = headA.next;
}
while(headB!=null){
if(set.contains(headB)){
return headB;
}
headB= headB.next;
}
return null;
}
}
/**
* 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) {
if(headA==null||headB==null){
return null;
}
ListNode pA = headA;
ListNode pB = headB;
while(pA!=pB){
pA = (pA == null?headB:pA.next);
pB = (pB == null?headA:pB.next);
}
return pA;
}
}
206. 反转链表
1.头插法
class Solution {
public ListNode reverseList(ListNode head) {
ListNode newhead = new ListNode(0);
ListNode curNode = head;
while(curNode!=null){
ListNode temp = curNode.next;
curNode.next = newhead.next;
newhead.next = curNode;
curNode = temp;
}
return newhead.next;
}
}
2.迭代插入法
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while(cur!=null){
ListNode temp = cur.next;
cur.next = pre;
pre =cur ;
cur = temp;
}
return pre;
}
}
234. 回文链表
1.传统的栈方法
import java.util.Stack;
class Solution {
public static boolean isPalindrome(ListNode head) {
Stack<ListNode> stack = new Stack<>();
int totalCount = 0;
ListNode cur = head;
while(cur!=null){
totalCount++;
cur = cur.next;
}
if(totalCount<2){
return true;
}
// 判断奇偶
if(totalCount%2==0){
int i = 0;
while(head!=null){
if(i<(totalCount/2)){
stack.push(head);
}else{
ListNode temp = stack.pop();
if(head.val!=temp.val){
return false;
}
}
head = head.next;
i++;
}
}else if(totalCount%2==1){
int i = 0;
while(head!=null){
if(i<(totalCount/2)){
stack.push(head);
}else if(i==totalCount/2){
// 不用处理
}else{
ListNode temp = stack.pop();
if(head.val!=temp.val){
return false;
}
}
head = head.next;
i++;
}
}
return true;
}
}
2.精简版本的栈
import java.util.Stack;
class Solution {
public static boolean isPalindrome(ListNode head) {
Stack<ListNode> stack = new Stack<>();
ListNode cur = head;
while(cur!=null){
stack.push(cur);
cur = cur.next;
}
while(head!=null){
if(head.val!=stack.pop().val){
return false;
}
head = head.next;
}
return true;
}
}
21. 合并两个有序链表
- 常规方法
/**
* Definition for singly-linked list.
*
*/
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if(list1==null){
return list2;
}
if(list2==null){
return list1;
}
// 比较大小
ListNode newHead = new ListNode(0);
ListNode curNode = newHead;
ListNode nodeA = list1;
ListNode nodeB = list2;
while(nodeA!=null && nodeB!=null){
if(nodeA.val<=nodeB.val){
curNode.next = nodeA;
nodeA = nodeA.next;
}else{
curNode.next = nodeB;
nodeB = nodeB.next;
}
curNode = curNode.next;
}
if(nodeA!=null){
curNode.next = nodeA;
}
if(nodeB!=null){
curNode.next = nodeB;
}
return newHead.next;
}
}
2. 两数相加
方法一:原始方法
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
if (l1 == null) {
return l2;
}
if (l2 == null) {
return l1;
}
ListNode newHead = new ListNode(0);
ListNode curNode = newHead;
Integer add = 0;
while (l1 != null || l2 != null) {
Integer l1Value = 0;
Integer l2Value = 0;
if (l1 != null) {
l1Value = l1.val;
}
if (l2 != null) {
l2Value = l2.val;
}
Integer sum = l1Value + l2Value + add;
Integer value = sum % 10;
add = sum / 10;
ListNode node = new ListNode(value);
curNode.next = node;
curNode = curNode.next;
if (l1 != null) {
l1 = l1.next;
}
if (l2 != null) {
l2 = l2.next;
}
}
if (add != 0) {
ListNode node = new ListNode(add);
curNode.next = node;
curNode = curNode.next;
}
return newHead.next;
}
}
方法二:递归
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
return this.addTwoNumbers2(l1, l2, 0);
}
public ListNode addTwoNumbers2(ListNode l1, ListNode l2, int a) {
if (l1 == null && l2 == null) {
return a == 0 ? null : new ListNode(a);
}
if (l1 != null) {
a += l1.val;
l1 = l1.next;
}
if (l2 != null) {
a += l2.val;
l2 = l2.next;
}
return new ListNode(a % 10, addTwoNumbers2(l1, l2, a / 10));
}
}