模拟算法题目
找出游戏的获胜者 (约瑟夫环)
class Solution {
public:
//约瑟夫环问题-模拟
int findTheWinner(int n, int k) {
//编号:0~n-1
if(n==1)return 1;
if(k==1)return n;
vector<bool>vis(n,false);
int rest=n;//剩余rest人
int i=0;
int cnt=0;
while(rest>1){
if(!vis[i]){
if(cnt+1==k){
cnt=0;
vis[i]=true;
--rest;
}else{
++cnt;
}
}
i=i==n-1?0:i+1;//模拟环
}
for(int i=0;i<n;++i){
if(!vis[i]){
return i+1;
}
}
return 0;//无意义的返回
}
};
屏幕可显示句子的数量 (模拟+循环节)
class Solution {
public:
int wordsTyping(vector<string>& sentence, int rows, int cols) {
int cnt=0;
int rest=cols;
int r=0;
int index=0;
bool is=false;
int size=sentence.size();
while(r<rows){
int len=index==size?sentence[0].length():sentence[index].length();
if(index==size){
index=0;
++cnt;
if(!is&&rest<sentence[0].length()){//判断是否出现循环节
++r;
//循环节行数r
cnt*=(rows/r);
r=rows-rows%r;
rest=cols;
is=true;
}
}
if(rest<=0||rest<len){
rest=cols;
++r;
}else{
rest-=len+1;
++index;
}
}
return cnt;
}
};
旋转图像
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n=matrix.size();
if(n==1)return;
for(int r=0;r<(n>>1);++r){//进行r轮
//每轮开始行row0=r,开始列col0=r;
//每轮的len=(n>>r);
int len=n-(r<<1);
int row0=r,col0=r;
int row1=r+len-1;
int col1=r+len-1;
for(int i=0;i<len-1;++i){//一次交换四条边的对应位置上的元素
int tmp=matrix[row0][col0+i];
matrix[row0][col0+i]=matrix[row1-i][col0];
matrix[row1-i][col0]=matrix[row1][col1-i];
matrix[row1][col1-i]=matrix[row0+i][col1];
matrix[row0+i][col1]=tmp;
}
}
}
};
分糖果 II
class Solution {
public:
vector<int> distributeCandies(int candies, int num_people) {
//1~n
//n+1~2n
//2n+1~
int k=0;
while(k*(1+k)/2<=candies){
k++;
}
k--;
int rest=candies-k*(1+k)/2;
//
int index=k%num_people;
index=(index==0?num_people-1:index-1);
vector<int>ans(num_people,0);
int round=(k%num_people==0?k/num_people-1:k/num_people)+1;
// cout<<round;
for(int i=0;i<=index;++i){
ans[i]=round*((round-1)*num_people+i+i+2)/2;
}
for(int i=index+1;i<num_people;++i){
ans[i]=(round-1)*((round-2)*num_people+i+i+2)/2;
}
if(rest!=0){
if(index!=num_people-1){
ans[index+1]+=rest;
}else{
ans[0]+=rest;
}
}
return ans;
}
};
Excel 表列序号
class Solution {
public:
int titleToNumber(string columnTitle) {
int i=0;
int ans=0;
while(i<columnTitle.length()){
int n=columnTitle[i]-'A'+1;
ans=ans*26+n;
++i;
}
return ans;
}
};
Excel表列名称
class Solution {
public:
string convertToTitle(int columnNumber) {
string ans;
while(columnNumber>0){
columnNumber--;
ans+=(char)('A'+columnNumber%26);
columnNumber/=26;
}
reverse(ans.begin(),ans.end());
return ans;
}
};
顺时针打印矩阵
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int>ans;
if(matrix.size()==0)return ans;
if(matrix[0].size()==1){
for(int i=0;i<matrix.size();++i){
ans.push_back(matrix[i][0]);
}
return ans;
}
int isVisited[matrix.size()][matrix[0].size()];
memset(isVisited,0,sizeof(isVisited));
for(int row=0;row<(matrix.size()>>1);++row){
int len1=matrix[0].size()-row*2;
int len2=matrix.size()-row*2;
int r1=row;
int c1=row;
int r2=r1+len2-1;
int c2=c1+len1-1;
// cout<<r1+" "<<r2+" "<<c1+" "<<c2<<endl;
for(int i=0;i<len1-1;++i){
if(isVisited[r1][c1+i]==0){
ans.push_back(matrix[r1][c1+i]);
isVisited[r1][c1+i]=1;
}else{
goto flag;
}
}
// ans.push_back(-1);
for(int i=0;i<len2-1;++i){
if(isVisited[r1+i][c2]==0){
ans.push_back(matrix[r1+i][c2]);
isVisited[r1+i][c2]=1;
}else{
goto flag;
}
}
for(int i=0;i<len1-1;++i){
if(isVisited[r2][c2-i]==0){
ans.push_back(matrix[r2][c2-i]);
isVisited[r2][c2-i]=1;
}else{
goto flag;
}
}
for(int i=0;i<len2-1;++i){
if(isVisited[r2-i][c1]==0){
ans.push_back(matrix[r2-i][c1]);
isVisited[r2-i][c1]=1;
}else{
goto flag;
}
}
}
if(matrix.size()%2==1){
int len=matrix[0].size()-matrix.size()/2*2;
for(int i=0;i<len;++i){
if(isVisited[matrix.size()/2][matrix.size()/2+i]!=1){
ans.push_back(matrix[matrix.size()/2][matrix.size()/2+i]);
}
}
}flag:
return ans;
}
};
圆形赛道上经过次数最多的扇区
解题思路:
中间的循环对最终的结果没有影响,关键在于 开始位置 和 结束位置 。
class Solution {
public:
vector<int> mostVisited(int n, vector<int>& rounds) {
vector<int>ans;
int start=rounds.front();
while(start!=rounds.back()){
ans.push_back(start);
start++;
start=start>n?start%n:start;
}
ans.push_back(start);
std::sort(ans.begin(),ans.end());
return ans;
}
};
字符串的左右移
class Solution {
public:
string stringShift(string s, vector<vector<int>>& shift) {
int left=0;
int right=0;
for(int i=0;i<shift.size();++i){
if(shift[i][0]==0){
left+=shift[i][1];
}else{
right+=shift[i][1];
}
}
if(left==right)return s;
else if(left>right){
left-=right;
left%=s.length();
s=s.substr(left,s.length())+s.substr(0,left);
return s;
}
right-=left;
right%=s.length();
s=s.substr(s.size()-right,s.length())+s.substr(0,s.length()-right);
return s;
}
};
可被 5 整除的二进制前缀
思路:
此题如果老老实实算出二进制数,很明显会 溢出 。
可被5整除的数字只跟该数字的最后一位数字(为0或5)有关系,于是不需要具体的算出二进制前缀对应的十进制整数是多少,只需 每次保留最后一位数字(保留用该数字对10取余的十进制整数的结果)就好,而下一个二进制前缀对应的十进制整数 = 上一次的结果左移一位(乘以2)的结果 + 这次的A[i](0或者1,正好对应十进制的0或者1)的结果。
class Solution {
public:
vector<bool> prefixesDivBy5(vector<int>& nums) {
int value=0;
vector<bool>ans;
for(int i=0;i<nums.size();++i){
value=(value<<1)+nums[i];
value%=10;
if(value==0||value==5){
ans.push_back(true);
}else{
ans.push_back(false);
}
}
return ans;
}
};
找出井字棋的获胜者
class Solution {
public boolean isWin(int[][] moves,List<Integer>list){
if(list.size()<3)return false;
for(int i=0;i<list.size();++i){
for(int j=0;j<list.size();++j){
if(j==i)continue;
for(int k=0;k<list.size();++k){
if(k==i||k==j)continue;
int ii=list.get(i);
int jj=list.get(j);
int kk=list.get(k);
if(moves[ii][0]==moves[jj][0]&&moves[kk][0]==moves[jj][0])return true;
if(moves[ii][1]==moves[jj][1]&&moves[kk][1]==moves[jj][1])return true;
if(moves[ii][0]*2==moves[jj][0]+moves[kk][0]&&moves[ii][1]*2==moves[jj][1]+moves[kk][1])return true;
if(moves[jj][0]*2==moves[ii][0]+moves[kk][0]&&moves[jj][1]*2==moves[ii][1]+moves[kk][1])return true;
if(moves[kk][0]*2==moves[jj][0]+moves[ii][0]&&moves[kk][1]*2==moves[jj][1]+moves[ii][1])return true;
}
}
}
return false;
}
public String tictactoe(int[][] moves) {
if(moves.length<5)return "Pending";
List<Integer>A=new ArrayList<>();
List<Integer>B=new ArrayList<>();
for(int i=0;i<moves.length;++i){
if((i&1)==0){
A.add(i);
}else{
B.add(i);
}
}
if(isWin(moves,A))return "A";
if(isWin(moves,B))return "B";
if(moves.length==9)return "Draw";
return "Pending";
}
}
圆圈中最后剩下的数字 (约瑟夫环)
class Solution {
public int lastRemaining(int n, int m) {
if(n==1)return 0;
if(m==1)return n-1;
List<Integer>list=new ArrayList<>();
for(int i=0;i<n;++i){
list.add(i);
}
int i=0;
while(list.size()>1){
i=(i+m-1)%(list.size());
list.remove(i);
}
return list.get(0);
}
}
旋转词
题目解析: KMP算法应用
import java.util.Scanner;
//模拟-旋转词
public class Main {
public static class KMP{
public String s1;
public String s2;//目标串
public int next[];
public KMP(String s1,String s2) {
this.s1=s1;
this.s2=s2;
if(s2.length()>0)next=new int[s2.length()];
}
public void getNextArray() {
if(s2.length()==1) {
next[0]=-1;
return;
}
next[0]=-1;
next[1]=0;
int i=2;
int cn=0;//从0开始与s2[i-1]比对
while(i<s2.length()) {
if(s2.charAt(next[i-1])==s2.charAt(cn)) {
next[i++]=++cn;
}else if(cn>0) {
cn=next[cn];
}else {//cn<=0
++i;
}
}
}
public int getIndexOf() {
if(s2.length()>s1.length()) {
return -1;
}
getNextArray();
int x=0;
int y=0;
while(x<s1.length()&&y<s2.length()) {
if(s1.charAt(x)==s2.charAt(y)) {
x++;
y++;
}
else if(next[y]==-1) {
x++;
}else {
y=next[y];
}
}
return y==s2.length()?x-y:-1;
}
}
public static boolean isRotateWord(String s1,String s2) {
if(s1.length()!=s2.length())return false;
s1+=s1;
//KMP判断s2是否是s1的字串
KMP kmp=new KMP(s1,s2);
return kmp.getIndexOf()!=-1?true:false;
}
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
int n,m;
n=scan.nextInt();
m=scan.nextInt();
scan.nextLine();
String s1,s2;
s1=scan.nextLine();
s2=scan.nextLine();
boolean ans=isRotateWord(s1,s2);
if(ans)System.out.println("YES");
else System.out.println("NO");
}
}
旋转矩阵
import java.util.*;
public class Solution {
public void process(int[][] mat,int a,int b,int c,int d){
for(int i=0;i<d-b;++i){
int tmp=mat[c-i][b];
mat[c-i][b]=mat[c][d-i];
mat[c][d-i]=mat[a+i][d];
mat[a+i][d]=mat[a][b+i];
mat[a][b+i]=tmp;
}
}
public int[][] rotateMatrix(int[][] mat, int n) {
// write code here
int a=0;
int b=0;
int c=n-1;
int d=n-1;
while(b<d){
process(mat,a++,b++,c--,d--);
}
return mat;
}
}