leetcode之模拟刷题总结2
1-重塑矩阵
题目链接:题目链接戳这里!!!
思路:模拟矩阵重塑过程,如果原始矩阵和重塑矩阵的元素个数不同,则不能完成重塑,反之,可以完成重塑,先把原始矩阵转换一维数组,再将一维数组转换为重塑矩阵。
AC代码如下:
class Solution {
public int[][] matrixReshape(int[][] mat, int r, int c) {
if(r*c!=mat.length*mat[0].length){
return mat ;
}
int [] temp = new int [r*c] ;
int idx = 0 ;
int [][] res = new int [r][c] ;
for(int i=0; i<mat.length; i++){
for(int j=0; j<mat[0].length; j++){
temp[idx++] = mat[i][j] ;
}
}
idx = 0 ;
for(int i=0; i<r; i++){
for(int j=0; j<c; j++){
res[i][j] = temp[idx++] ;
}
}
return res ;
}
}
也可以这样写,直接将二维矩阵转换成对应的二维矩阵,效率更高。
class Solution {
public int[][] matrixReshape(int[][] mat, int r, int c) {
if(r*c!=mat.length*mat[0].length){
return mat ;
}
int [][] res = new int [r][c] ;
for(int i=0; i<r*c; i++){
res[i/c][i%c] = mat[i/mat[0].length][i%mat[0].length] ;
}
return res ;
}
}
2-Fizz Buzz
题目链接:题目链接戳这里!!!
思路:很水的题,直接判断,加入集合就可以。
class Solution {
public List<String> fizzBuzz(int n) {
List<String> list = new ArrayList<>() ;
for(int i=1; i<=n; i++){
if(i%3==0 && i%5==0){
list.add("FizzBuzz") ;
}else if(i%3==0){
list.add("Fizz") ;
}else if(i%5==0){
list.add("Buzz") ;
}else{
list.add(String.valueOf(i)) ;
}
}
return list ;
}
}
3-求解方程
题目链接:题目链接戳这里!!!
思路:将字符串所有“-”符号前面添加“+“,然后按照等号将字符串划分成两段,左边的和右边的都按照”+“划分成字符串数组,然后对左右两个字符串进行处理,根据系数判断有无解。
AC代码如下:
class Solution {
public String solveEquation(String equation) {
int idx = 0 ;
for(int i=0; i<equation.length(); i++){
if(equation.charAt(i)=='-'){
equation = equation.substring(0,i) + "+" + equation.substring(i) ;
i++ ;
}
}
for(int i=0; i<equation.length(); i++){
if(equation.charAt(i)=='='){
idx=i ;
}
}
String left = equation.substring(0,idx) ;
String right = equation.substring(idx+1,equation.length()) ;
String [] l = left.split("[+]") ;
String [] r = right.split("[+]") ;
int a1=0, a2=0, b1=0, b2=0 ;
for(int i=0; i<l.length; i++){
if( !l[i].equals("") && !contains(l[i]) ){
a1 += Integer.parseInt(l[i]) ;
}else if(!l[i].equals("") && contains(l[i])){
if(l[i].length()==1){
b1 += 1 ;
}else if(l[i].length()==2 && l[i].charAt(0)=='-'){
b1 -= 1 ;
}
else{
b1 += Integer.parseInt(l[i].substring(0,l[i].length()-1)) ;
}
}
}
for(int i=0; i<r.length; i++){
if(!contains(r[i]) && !r[i].equals("")){
a2 += Integer.parseInt(r[i]) ;
}else if(contains(r[i]) && !r[i].equals("")){
if(r[i].length()==1){
b2 += 1 ;
}else if(r[i].length()==2 && r[i].charAt(0)=='-'){
b2 -= 1 ;
}
else{
b2 += Integer.parseInt(r[i].substring(0,r[i].length()-1)) ;
}
}
}
if(b1!=b2){
return "x=" + (a2-a1)/(b1-b2) ;
}else if(a1!=a2){
return "No solution" ;
}else{
return "Infinite solutions" ;
}
}
public boolean contains(String s){
if(s.equals("")){
return false ;
}
if(s.charAt(s.length()-1)=='x'){
return true ;
}
return false ;
}
}
4-机器人能否返回原点
题目链接:题目链接戳这里!!!
思路:记录U,D,R,L的个数,当且仅当U等于D且R等于L时候,可以 返回到原点,否则,不能返回到原点。
class Solution {
public boolean judgeCircle(String moves) {
int cntU=0, cntD=0, cntL=0, cntR=0 ;
for(int i=0; i<moves.length();i++){
if(moves.charAt(i)=='U'){
cntU ++ ;
}else if(moves.charAt(i)=='D'){
cntD ++ ;
}else if(moves.charAt(i)=='L'){
cntL ++ ;
}else if(moves.charAt(i)=='R'){
cntR ++ ;
}
}
return cntR==cntL && cntD==cntU ;
}
}
5-模拟机器人行走
题目链接:题目链接戳这里!!!
思路:用set集合存储障碍物坐标,定义四个方向,根据命令模拟运动,同时计算最大欧式距离。
AC代码如下:
class Solution {
public int robotSim(int[] commands, int[][] obstacles) {
Set<String> set = new HashSet<>() ;
for(int [] obstacle : obstacles){ //set集合存储障碍物坐标
set.add(obstacle[0]+","+obstacle[1]) ;
}
//定义北,东,南,西四个方向
int [] dx = {0,1,0,-1} ;
int [] dy = {1,0,-1,0} ;
int cur=0, x=0, y=0;
int tx, ty ;
int ans = 0 ;
for(int command:commands){
if(command>0){
for(int i=0; i<command; i++){
tx = x + dx[cur] ;
ty = y + dy[cur] ;
if(set.contains(tx+","+ty)){
break ;
}
x = tx ;
y = ty ;
ans = Math.max(ans,x*x+y*y) ;
}
}else{
cur = command==-1 ? (cur+1)%4 : (cur+3)%4 ;
}
}
return ans ;
}
}
6-棒球比赛
题目链接:题目链接戳这里!!!
思路1:转换成list结果完成相应的操作。
由于类型的转换较多,效率不是很高。
class Solution {
public int calPoints(String[] ops) {
List<String> list = new ArrayList<>() ;
for(int i=0; i<ops.length; i++){
list.add(ops[i]) ;
}
for(int i=0; i<list.size(); i++){
if(list.get(i).equals("C")){
list.remove(i) ;
list.remove(i-1) ;
i -= 2 ;
}else if(list.get(i).equals("D")){
int value = Integer.parseInt(list.get(i-1))*2 ;
list.set(i,String.valueOf(value)) ;
}else if(list.get(i).equals("+")){
int sum = Integer.parseInt(list.get(i-1))+Integer.parseInt(list.get(i-2)) ;
list.set(i,String.valueOf(sum)) ;
}
}
int s = 0 ;
for(int i=0; i<list.size(); i++){
s += Integer.parseInt(list.get(i)) ;
}
return s ;
}
}
思路2:直接用整数数组记录,效率提升了很多。
class Solution {
public int calPoints(String[] ops) {
int [] res = new int [ops.length] ;
int sum = 0 ;
int j = 0 ;
for(int i=0; i<ops.length; i++){
switch(ops[i]){
case "C": res[j-1]=0 ;j--; break ;
case "D":res[j] = 2*res[j-1]; j++; break ;
case "+":res[j] = res[j-1] + res[j-2]; j++ ; break ;
default: res[j] = Integer.parseInt(ops[i]) ; j++; break;
}
}
for(int s : res){
sum += s ;
}
return sum ;
}
}
7-按递增顺序显示卡牌
题目链接:题目链接戳这里!!!
思路:使用队列,按照反着的过程模拟一边,最后输出数组即可,有点绕,动手画一画就明白了。
class Solution {
public int[] deckRevealedIncreasing(int[] deck) {
Arrays.sort(deck) ;
Queue<Integer> queue = new LinkedList<>() ;
for(int i=deck.length-1; i>=0; i--){
if(queue.isEmpty()){
queue.add(deck[i]) ;
continue ;
}
queue.add(queue.poll()) ;
queue.add(deck[i]) ;
}
for(int i=deck.length-1; i>=0; i--){
deck[i] = queue.poll() ;
}
return deck ;
}
}
8-查询后的偶数和
题目链接:题目链接戳这里!!!
思路1:每次修改nums数组,然后求偶数和,这样虽然可以AC,但是由于每次都要求和,导致浪费时间,效率过低。
class Solution {
public int[] sumEvenAfterQueries(int[] nums, int[][] queries) {
int [] res = new int [nums.length] ;
int j = 0 ;
for(int i=0; i<queries.length; i++){
int num = queries[i][0] ;
int idx = queries[i][1] ;
nums[idx] += num ;
res[j++] += getSum(nums) ;
}
return res ;
}
public int getSum(int [] nums){
int sum = 0 ;
for(int n : nums){
if((n&1)==0){
sum += n ;
}
}
return sum ;
}
}
思路2:提前求好和,如果当前修改的值影响偶数和,做对偶数和进行处理。
AC代码如下:
class Solution {
public int[] sumEvenAfterQueries(int[] nums, int[][] queries) {
int [] res = new int [nums.length] ;
int sum = 0 ;
for(int num : nums){
if(num%2==0){
sum += num ;
}
}
for(int i=0; i<queries.length; i++){
int num = queries[i][0] ;
int idx = queries[i][1] ;
if(nums[idx]%2==0){
sum -= nums[idx] ;
}
nums[idx] += num ;
if((nums[idx])%2==0){
sum += nums[idx];
}
res[i] = sum ;
}
return res ;
}
}
9-笨阶乘
题目链接:题目链接戳这里!!!
思路:就是将四个分成一组,用递归和循环都可以。
class Solution {
public int clumsy(int n) {
return f(n, 1) ;
}
public int f(int n, int prefix){
if(n==0){
return 0 ;
}
if(n==1){
return 1*prefix ;
}
if(n==2){
return 2*prefix ;
}
if(n==3){
return 6*prefix ;
}
return prefix*(n)*(n-1)/(n-2)+(n-3) + f(n-4, -1) ;
}
}
循环的写法,first标记是否执行第一次,每次四个一组,够分组的就执行循环里面,当不足4个,则判断是否执行过,若执行过,则后面的都是减,否则都是加。
class Solution {
public int clumsy(int n) {
int sum = 0 ;
boolean first = true ;
while(n-4>=0){
if(first){
sum += n*(n-1)/(n-2)+(n-3) ;
}else{
sum += -(n)*(n-1)/(n-2)+(n-3) ;
}
first = false ;
n = n-4 ;
}
if(first==false){
if(n==3){
sum -= 6 ;
}else if(n==2){
sum -= 2 ;
}else if(n==1){
sum -= 1 ;
}
}else{
if(n==1){
return 1;
}else if(n==2){
return 2 ;
}else if(n==3){
return 6 ;
}
}
return sum ;
}
}
10-验证栈序列
题目链接:题目链接戳这里!!!
思路:使用栈去模拟进栈和出栈的过程,如果最后能全部出栈,则满足要求,否则不满足要求。
class Solution {
public boolean validateStackSequences(int[] pushed, int[] popped) {
Stack<Integer> stack = new Stack<>() ;
int j = 0 ;
for(int i=0; i<popped.length; i++){
stack.push(pushed[i]) ;
while(!stack.isEmpty() && stack.peek()==popped[j]){
stack.pop() ;
j++ ;
}
}
return stack.isEmpty() ;
}
}