测开力扣面试常考简单编程题------手撕
20.有效的括号
题意:找匹配的括号对
class Solution {
public boolean isValid(String s) {
int n=s.length();
if(n%2!=0){
return false;
}
Map<Character,Character> map=new HashMap<>();
map.put('}','{');
map.put(']','[');
map.put(')','(');
Stack<Character> Stack=new Stack<>();
for(int i=0;i<n;i++){
char ch=s.charAt(i);
if(map.containsKey(ch)){
if(Stack.isEmpty() || Stack.pop()!=map.get(ch)){
return false;
}else{
continue;
}
}
Stack.push(ch);
}
if(!Stack.isEmpty()){
return false;
}
return true;
}
}
1 思路:
1)临界情况: 求字符串长度,长度若为奇数,则肯定不存在括号对
2)遍历字符串中的字符
2.1当map中不存在键值时,直接入栈
2.2存在时候,看栈顶元素是否和他匹配,当前栈不为空 (若栈为空,或者不匹配,则返回false)
3)遍历完之后,看栈中是否为空,不为空,则代表有没有匹配完的,返回false;
2 数据结构:
用Map存储括号对,用Stack完成匹配
Map<Character,Character> map=new HashMap<>();
Stack stack=new Stack<>();
3 常用API:
map.containsKey(ch);
map.put(a,b);
map.get(键值)//返回值
stach.push(a);
stack.pop();
stack.peek();//不返回
stack.isEmpty();
169.多数元素
题意:给一个数组,找到数组中元素个数最多(大于数组长度的一半)的数字
class Solution {
public int majorityElement(int[] nums) {
Map<Integer,Integer> res=new HashMap<>();
for(int i:nums){
if(res.containsKey(i)){
res.put(i,res.get(i)+1);
}else{
res.put(i,1);
}
}
//依次遍历键值对,找到最大的数字
Map.Entry<Integer,Integer> max=null;
for(Map.Entry<Integer,Integer> i:res.entrySet()){
if(max==null || i.getValue()>max.getValue()){
max=i;
}
}
return max.getKey();
}
}
class Solution {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length/2];
}
}
1 思路1:
1)对数组进行排序,然后找到中间的哪个数字即可
缺点:
复杂度较高,不推荐
1 思路2:
1)用HashMap存储键值对,数字-个数
2)遍历HashMap,找到最大值的元素,返回键即可
2 数据结构
HashMap即可
键值对 Map.Entry<Integer,Integer> max=null;
API:
map: 取map中的键值对,map.entrySet(); map.get(i); map.containsKey(i);
Map.Entry<> a : a.getValue() a.getKey()
1 两数之和
题意 给一个数组和target,返回数组中和为target的两个下标(数组中只有一种答案)
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> temp=new HashMap<>();
for(int i=0;i<nums.length;i++){
if(temp.containsKey(target-nums[i])){
return new int[]{
temp.get(target-nums[i]),i};
}
temp.put(nums[i],i);
}
return new int[]{
-1,-1};
}
}
1 思路:
1)用Map存储遍历过的数组的值和下标
2)如果Map中存在 target-当前元素,那么返回该当前的坐标和(target-当前元素)对应的下标(即存储的下标值)
2 数据结构
Map: 存储的键值对是 数组元素-下标
API:
Map : containsKey();
206 反转链表
题意: 反转一个链表
/**
* 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 reverseList(ListNode head) {
ListNode pre=null,cur=head,next=head;
while(cur!=null){
next=cur.next;
cur.next=pre;
pre=cur;
cur=next;
}
return pre;
}
}
注意:
在链表中的走向,最容易出现 cur.next=pre; cur=cur.next;这是一个环形的链表;这时候需要借助一个temp节点,保存next
1 思路:
1)1-2-3-4-5-null 可以创建一个 pre =null 再改变指针的指向
2)pre = null cur=head,next=head
3) 当 cur不是空的时候
3.1)保存next=cur.next;
3.2) cur.next=pre,pre=cur,cur=next
3.3) 返回 pre (因为cur 在 null上)
2 数据结构
链表节点 pre cur next
注意先后顺序和是否为空
141 环形链表
题意: 判断链表中是否有环,返回布尔类型
/**
* 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> temp=new HashSet<>();
ListNode cur=head;
while(cur!=null){
if(!temp.add(cur)){
return true;
}
temp.add(cur);
cur=cur.next;
}
return false;
}
}
1 思路:
1)遍历链表节点(当前节点不为空时候),若当前节点不能添加进Set,就代表有相同的节点,返回true
2) 否则返回false;
2 数据结构
环形链表必定有一个相交的节点,即重复的节点,用Set结构,看是否能添加进去
API:
Set : set.add(i);//返回的是boolean类型
53 最大子序列和
题意: 给个数组,求数组中连续的子序列和的最大值
class Solution {
public int maxSubArray(int[] nums) {
int max=nums[0];
for(int i=1;i<nums.length;i++){
nums[i]+=Math.max(0,nums[i-1]);
max=Math.max(max,nums[i]);
}
return max;
}
}
1 思路:
1)遍历时,从索引1开始,(求和)当前的数+前一个数的最大值(0或者大于0的本身,才有相加的意义)
2)求最大值,当前的最大值max和更新后的num[i]中的更大的一个数
2 数据结构
本题是数学题,主要看思路
未用到 API Math.max();
83 删除排序链表中的重复节点
题意:链表中有重复的节点,删除链表重复的节点
/**
* 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 deleteDuplicates(ListNode head) {
ListNode temp=head;
while(temp!=null && temp.next!=null){
if(temp.val==temp.next.val){
temp.next=temp.next.next;
}else{
temp=temp.next;
}
}
return head;
}
}
注意: 一条语句错了,很容易逻辑错误,面试不要单独领出来说,注意即可
1 思路:
1)定义一个cur指针 cur和cur.next比较,如果相等,则cur.next=cur.next.next;否则正常指向下一个
2)返回head即可
2 数据结构
注意循环找下一个不相等的链表结点
415 字符串相加
题意: 两个字符串相加,返回字符串
class Solution {
public String addStrings(String num1, String num2) {
int i=num1.length()-1;
int j=num2.length()-1;
int add=0;
StringBuffer sb=new StringBuffer();
while(i>=0 || j>=0 || add!=0){
int x=i>=0?num1.charAt(i)-'0':0;
int y=j>=0?num2.charAt(j)-'0':0;
int sum=x+y+add;
sb.append(sum%10);
add=sum/10;
i--;
j--;
}
sb.reverse();
return sb.toString();
}
}
1 思路:
1)双指针,从后往前遍历字符串,并且相加,定义进位
2)如果一个字符串的索引不是>=0,那么取值为0
注意:最后一位还有一个进位,也要相加
2 数据结构
StringBuffer: 变长,可以添加字符
API:
StringBuffer sb.append(),sb.reverse(), sb.tostring()
704 二分查找
题意: 排序数组的二分查找
class Solution {
public int search(int[] nums, int target) {
int left=0,right=nums.length-1;
while(left<=right){
//注意边界条件
int base=(left+right)/2;
if(target==nums[base]){
return base;
}else if(target>nums[base]){
left=base+1;
}else{
right=base-1;
}
}
return -1;
}
}
1 思路:
1)定义左右索引,如果左<=右 定义Mid索引,targe和中间值arr[mid]比对
2) 如果target小于 中间值,right=mid-1;
如果target大于中间值,left=mid+1;
如果等于中间值, 返回索引
2 数据结构
数组:注意循环和边界条件
232 用栈实现队列
栈是先进后出,队列是先进先出
主要实现四个函数:入队push 出队pop 对顶 peek 为空isEmpty
class MyQueue {
/*
Stack<Integer> d1=new Stack<>();
Stack<Integer> d2=new Stack<>();
*/
Deque<Integer> d1=new LinkedList<>();
Deque<Integer> d2=new LinkedList<>();
/** Initialize your data structure here. */
public MyQueue() {
}
/** Push element x to the back of queue. */
public void push(int x) {
d1.push(x);
}
/** Removes the element from in front of queue and returns that element. */
public int pop() {
if(d2.isEmpty()){
while(!d1.isEmpty()){
d2.push(d1.pop());
}
}
return d2.pop();
}
/** Get the front element. */
public int peek() {
if(d2.isEmpty()){
while(!d1.isEmpty()){
d2.push(d1.pop());
}
}
return d2.peek();
}
/** Returns whether the queue is empty. */
public boolean empty() {
return d1.isEmpty() && d2.isEmpty();
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = new MyQueue();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.peek();
* boolean param_4 = obj.empty();
*/
1 思路:
1)用两个栈,一个是数字栈,一个是辅助栈;
2) 入队列时候,直接将数字加入到 主栈即可;出队和队顶元素需要从辅助栈中,当辅助栈为空时候,需要将主栈元素移动到辅助栈中;是否为空,必须两个栈都为空才行
2 数据结构
栈: 栈的API都可以用,.push() .pop() .peek() . isEmpty()
160 相交链表
两个链表可能有相交的节点,也可能没有相交的节点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = n