目录
2、lmplement Queue using Stacks
3、lmplement Stack using Queues
5、Remove All Adjacent Duplicates In String
6、Evaluate Reverse Polish Notation
1、替换数字
给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。
例如,对于输入字符串 "a1b2c3",函数应该将其转换为 "anumberbnumbercnumber"。
对于输入字符串 "a5b",函数应该将其转换为 "anumberb"
输入:一个字符串 s,s 仅包含小写字母和数字字符。
输出:打印一个新的字符串,其中每个数字字符都被替换为了number
样例输入:a1b2c3
样例输出:anumberbnumbercnumber
数据范围:1 <= s.length < 10000。
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
String ss=sc.next();
int len=ss.length();
for(int i=0;i<ss.length();i++){
//这里ss.length();注意不能用会变的len当做长度
if(ss.charAt(i)>='0'&&ss.charAt(i)<='9'){
len+=5;
}
}
char[] newSS=new char[len];
len=len-1;
for(int i=ss.length()-1;i>=0;i--){
if(ss.charAt(i)>='0'&&ss.charAt(i)<='9'){
//这里犯错了,数组的索引从len-1开始,不是从len
newSS[len--]='r';
newSS[len--]='e';
newSS[len--]='b';
newSS[len--]='m';
newSS[len--]='u';
newSS[len--]='n';
}
else{
newSS[len--]=ss.charAt(i);
}
}
System.out.println(new String(newSS));
}
}
纠正自己代码习惯错误:
(1)注意一下是否可以用后面会变化的变量来当作for循环的结束条件
(2)数组的长度是length 字符串的长度是length()
(3)注意数组的末尾的下标是 【 len-1】
java栈的基本方法 pop push peek isEmpty
java队列的基本方法 add poll peek isEmpty
2、lmplement Queue using Stacks用栈实现队列
Implement a first in first out (FIFO) queue using only two stacks. The implemented queue should support all the functions of a normal queue (push
, peek
, pop
, and empty
).
Implement the MyQueue
class:
void push(int x)
Pushes element x to the back of the queue.int pop()
Removes the element from the front of the queue and returns it.int peek()
Returns the element at the front of the queue.boolean empty()
Returnstrue
if the queue is empty,false
otherwise
class MyQueue {
/**
需要2个栈实现一个队列,输入栈就是照常输入,再来一个输出栈就是数字顺序再倒过来,就恢复正常队列顺序了
push:数据放进输入栈
pop:输出栈如果为空,就把进栈数据【全部导入】进来,再从出栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以了
peek:和pop逻辑一致
Empty:判断2个栈都为空才返回空
*/
Stack<Integer> in;
Stack<Integer> out;
public MyQueue() {
in =new Stack<>();
out=new Stack<>();
}
public void push(int x) {
in.push(x);
}
public int pop() {
pushInToOut();
return (out.pop());
}
public int peek() {
pushInToOut();
return( out.peek());
}
public boolean empty() {
if(in.isEmpty()&&out.isEmpty())
return true;
return false;
}
public void pushInToOut(){
if(out.isEmpty()){
while(!in.isEmpty()){
int xx=in.pop();
out.push(xx);
}
}
}
}
/**
* 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();
*/
3、lmplement Stack using Queues用队列实现栈
mplement a last-in-first-out (LIFO) stack using only two queues. The implemented stack should support all the functions of a normal stack (push
, top
, pop
, and empty
).
Implement the MyStack
class:
void push(int x)
Pushes element x to the top of the stack.int pop()
Removes the element on the top of the stack and returns it.int top()
Returns the element on the top of the stack.boolean empty()
Returnstrue
if the stack is empty,false
otherwise.
class MyStack {
Queue<Integer> que;
/**
使用一个队列实现
当需要pop的时候,把前面所有元素重新添加到队尾,然后队列头部就是之前的最后一个元素
peak:这里需要注意,获取最后一个元素,只能先pop一下,然后再重新添加回去
*/
public MyStack() {
que=new LinkedList<>();//Java队列使用链表实现
}
public void push(int x) {
que.add(x);
}
public int pop() {
moveToBack();
return que.poll();
}
public int top() {
// moveToBack();
// int x=que.poll();
// que.add(x);
// return x;
int x=pop();
que.add(x);
return x;
}
public boolean empty() {
return que.isEmpty();
}
public void moveToBack(){
int size=que.size();
while(size>1){
que.add(que.poll());
size--;
}
}
}
/**
* Your MyStack object will be instantiated and called as such:
* MyStack obj = new MyStack();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.top();
* boolean param_4 = obj.empty();
*/
4、Valid Parentheses有效的括号
Given a string s
containing just the characters '('
, ')'
, '{'
, '}'
, '['
and ']'
, determine if the input string is valid.
An input string is valid if:
- Open brackets must be closed by the same type of brackets.
- Open brackets must be closed in the correct order.
- Every close bracket has a corresponding open bracket of the same type.
class Solution {
public boolean isValid(String s) {
/**
括号匹配,使用一个栈实现
当遇到左括号,就push对应匹配的右括号
当遇到右括号,需要检查一下:
(1)栈是否是空的,空的那肯定是不匹配了
(2)栈不为空,比较栈顶部的右括号和当前遍历的右括号是否相同,不同就返回false,
如果相同就是需要消消乐,把栈里面的首部元素删除
*/
Stack<Character> stack=new Stack<>();
for(int i=0;i<s.length();i++){
if(s.charAt(i)=='('){
stack.push(')');
}
else if(s.charAt(i)=='{'){
stack.push('}');
}
else if(s.charAt(i)=='['){
stack.push(']');
}
else if(stack.isEmpty()||s.charAt(i)!=stack.peek()){
return false;
}
else{
stack.pop();
}
}
return stack.isEmpty();
}
}
5、Remove All Adjacent Duplicates In String删除字符串中的所有相邻重复项
You are given a string s
consisting of lowercase English letters. A duplicate removal consists of choosing two adjacent and equal letters and removing them.
We repeatedly make duplicate removals on s
until we no longer can.
Return the final string after all such duplicate removals have been made. It can be proven that the answer is unique.
class Solution {
public String removeDuplicates(String s) {
/**
这个和括号匹配问题相似,就是消消乐
最后剩下的元素需要转换成string
*/
Stack<Character> stack=new Stack<>();
for(int i=0;i<s.length();i++){
if(!stack.isEmpty()&&stack.peek()==s.charAt(i)){
stack.pop();
}
else{
stack.push(s.charAt(i));
}
}
char cc[]=new char[stack.size()];
int j=stack.size()-1;
while(!stack.isEmpty()){
cc[j--]=stack.pop();
}
return new String(cc);
}
}
6、Evaluate Reverse Polish Notation逆波兰表达式求值
You are given an array of strings tokens
that represents an arithmetic expression in a Reverse Polish Notation.
Evaluate the expression. Return an integer that represents the value of the expression.
Note that:
- The valid operators are
'+'
,'-'
,'*'
, and'/'
. - Each operand may be an integer or another expression.
- The division between two integers always truncates toward zero.
- There will not be any division by zero.
- The input represents a valid arithmetic expression in a reverse polish notation.
- The answer and all the intermediate calculations can be represented in a 32-bit integer.
class Solution {
public int evalRPN(String[] tokens) {
/**
遇到数字则入栈;遇到运算符则取出栈顶两个数字进行计算,并将结果压入栈中
这里需要注意数字先后顺序,对于除法和减法是有顺序要求的
*/
Stack<Integer> num=new Stack<>();
Stack<Integer> opt=new Stack<>();
for(int i=0;i<tokens.length;i++){
if(tokens[i].equals("+")){
int res=num.pop()+num.pop();
num.push(res);
}
else if(tokens[i].equals("-")){
int n1=num.pop();
int n2=num.pop();
num.push(n2-n1);
}
else if(tokens[i].equals("/")){
int n1=num.pop();
int n2=num.pop();
num.push(n2/n1);
}
else if(tokens[i].equals("*")){
int res=num.pop()*num.pop();
num.push(res);
}
else{
num.push(Integer.parseInt(tokens[i]));
}
}
return num.pop();
}
}
7、Sliding Window Maximum滑动窗口最大值
You are given an array of integers nums
, there is a sliding window of size k
which is moving from the very left of the array to the very right. You can only see the k
numbers in the window. Each time the sliding window moves right by one position.
Return the max sliding window.
Example 1:
Input: nums = [1,3,-1,-3,5,3,6,7], k = 3 Output: [3,3,5,5,6,7] Explanation: Window position Max --------------- ----- [1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5 3 6 7 3 1 3 [-1 -3 5] 3 6 7 5 1 3 -1 [-3 5 3] 6 7 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7
class Mydequeue{
Deque<Integer> que;
public Mydequeue(){
que=new LinkedList<>();
//que的方法有 peek poll add addLast removeLast getLast
}
public int peek(){
//直接返回头部元素值,也是最大值
return que.peek();
}
public void add(int val){
//添加元素,不为空且val如果大于队列末尾元素就要移除末尾元素,这个是循环的,保证val插入是形成递减队列
//比如 5 2 3插入4 那最终队列为5 4
//3 2 1 插入 5 那最终队列为5
while(!que.isEmpty()&&val>que.getLast()){
que.removeLast();//移除尾部
}
//这里的val是肯定要插入的,记得是插入尾部
que.addLast(val);
}
public void poll(int val){
//如果移除的元素等于队列头部元素,那就弹出
if(val==que.peek()){
que.poll();
}
}
}
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
/**
利用一个队列dequeue维护有可能成为窗口里最大值的元素,同时排序由大到小
poll:如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
add:如果add的元素value大于入口元素的数值,那么就将队列入口的元素弹出,
直到add元素的数值小于等于队列入口元素的数值
nums = [1,3,-1,-3,5,3,6,7], k = 3
滑动窗口 队列元素的值变化 每次滑动到一个新的窗口,队列只维持最大元素开始的顺序
(1) 3,-1
(2)3,-1,-3
(3)5
(4)5 3
(5)6
(6)7
这里注意,队列里面的元素是单调递减的,并且元素之间的顺序和原始数组中元素的顺序是相对一致的
所以不可能出现队列中第二最大值先被弹出来,肯定都是【比他最大的值且在数组中排序在它前面的】先被弹出来,再到自己
*/
Mydequeue que=new Mydequeue();
int[] res=new int[nums.length-k+1];
for(int i=0;i<k;i++){
que.add(nums[i]);
}
res[0]=que.peek();//res返回结果数组
for(int i=k,j=1;i<nums.length;i++,j++){
que.add(nums[i]);//移动窗口进来新得元素
que.poll(nums[i-k]); //移动窗口移除旧得元素
res[j]=que.peek();
}
return res;
}
}
8、Top K Frequent Elements前 K 个高频元素
Given an integer array nums
and an integer k
, return the k
most frequent elements. You may return the answer in any order.
Example 1:
Input: nums = [1,1,1,2,2,3], k = 2 Output: [1,2]
Example 2:
Input: nums = [1], k = 1 Output: [1]
class Solution {
public int[] topKFrequent(int[] nums, int k) {
/**
思路:
1、统计每个数字出现频率:用map
2、对频率进行排序,选择k个最大的频率:使用优先队列priorityqueue
优先队列的底层实现是堆(大顶堆和小顶堆)
先把每个频率放入堆中进行排序,超过k个就把堆顶最小值弹出来,遍历结束剩下的就全部是k个最大的
*/
Map<Integer,Integer> map=new HashMap<>();
for(int n:nums){
//统计频率
map.put(n,map.getOrDefault(n,0)+1);
}
//实现小顶堆,堆顶元素是最小值
o1 - o2 是升序排序从小到大,o2 - o1 是降序排序,
//这里优先队列的元素是一对二元组,为了对应数字和频率
PriorityQueue<int[]> pq=new PriorityQueue<>((a,b)->a[1]-b[1]);
//这里a1-b1如果结果为负,那么第一个形参a排前面,也就是a的频率低就排在前面,所以就是升序
for(var mm:map.entrySet()){//这里的var也可以变成Map.Entry<Integer,Integer>
int[] tem=new int[2];
tem[0]=mm.getKey();
tem[1]=mm.getValue();
pq.add(tem);//先添加再判断是否超过k个,超过就弹出堆顶最小值
if(pq.size()>k){
pq.poll();
}
}
int[] res=new int[k];
int j=0;
while(!pq.isEmpty()){
res[j++]=pq.poll()[0];
}
return res;
}
}