以下题目是leetcode上题型偏向于找规律性质的题目汇总
面试题 01.08 零矩阵
第一反应:暴力解决,想到要去降低时间复杂度,暴力每次都要重复遍历为0已经遍历的行或者列所以想到记录已经是0的行和列。数据结构实现:bolean数组,row[]和col[] 数组下标即是代表相对应的行以及列来表示该行及列是否应该都化为0,该方法的时间复杂度是O(m✖n) :两次遍历二维数组
class Solution {
public void setZeroes(int[][] matrix) {
int m = matrix.length,n = matrix[0].length;
int[] row = new int[m];
int[] col = new int[n];
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(matrix[i][j]==0){
row[i]=1;
col[j]=1;
}
}
}
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(row[i]==1||col[j]==1){ //表示这个点有行或者列经过
matrix[i][j]=0;
}
}
}
}
}
面试题 16.11.跳水板
一个等差数列
class Solution {
public int[] divingBoard(int shorter, int longer, int k) {
if(k==0){
return new int[0];
}
if(shorter==longer){
//比较难想到
return new int[]{shorter*k};
}
int[] lengths = new int[k+1];
for(int i=0;i<=k;i++){
lengths[i]=i*longer+(k-i)*shorter;
}
return lengths;
}
}
一次编辑
这道题目可以这样思考:1.如果两个字符串完全相等则满足 2.如果两个字符串需要一次编辑,可能的情况也分为需要插入元素、需要删除一个元素、替换一个元素,所以两个字符串长度必须相等或者只相差一。代码实现思路也可以同样分为两个模块,两个长度相等的字符串,用一个数记录两个字符串不同的字符,不同的数只能是0或者1,长度相差为1,不同的字符只能为1个
class Solution {
public boolean oneEditAway(String first, String second) {
int lf=first.length();
int ls=second.length();
//保证second>first
if(lf>ls){
return oneEditAway(second,first);
}
//case1 两个字符串相差大于1返回false
if(ls-lf>1){
return false;
}
//case2 两个字符串相等
int count=0;
if(lf==ls){
for(int i=0;i<lf;i++){
if(second.charAt(i)!=first.charAt(i)){
count++;
}
}
//如果不同的字符大于1则返回false
if(count>1) return false;
else return true;
}
//case3 两个字符串相差为1
int i=0;
int weiyi=0;
while(i<lf){
if(first.charAt(i)!=second.charAt(i+weiyi)){
if(++weiyi>1){
return false;
}
}else{
i++;
}
}
return true;
}
}
珠玑妙算
题意理解:猜中:位置一样,颜色一样;伪猜中:位置不一样,颜色一样;同时,猜中不能算是伪猜中
class Solution {
public int[] masterMind(String solution, String guess) {
boolean[] used = new boolean[4];
int[] ans = new int[2];
//case1 先找猜中的次数
int answer = 0;
for(int i=0;i<4;i++){
if(solution.charAt(i)==guess.charAt(i)){
answer++;
used[i]=1; //表示该元素用过了
}
}
ans[0]=answer;
//case2
int answerfake = 0; //伪猜中
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(used)
}
}
ans[1]=answerfake;
return ans;
}
}
#字游戏
class Solution {
public String tictactoe(String[] board) {
int N = board.length; //N✖N的棋盘
boolean hasBlank = false; //表示是否有空格
int rowX,rowO,colX,colO;
for(int i=0;i<N;i++){
rowX=0;rowO=0;colX=0;colO=0;
for(int j=0;j<N;j++){
if(board[i].charAt(j)==' ') hasBlank=true;
if(board[i].charAt(j)=='X') rowX++;
else if(board[i].charAt(j)=='O') rowO++;
if(board[j].charAt(i)=='X') colX++;
else if(board[j].charAt(i)=='O') colO++;
}
if(rowX==N||colX==N) return "X";
if(rowO==N||colO==N) return "O";
}
//对角线检测
int leftTopX=0; //左上角对角线检测X
int leftTopO=0; //左上角对角线检测O
int rightTopX=0; //右上角对角线检测X
int rightTopO=0; //右上角对角线检测O
for(int i=0;i<N;i++){
if(board[i].charAt(i)=='X') leftTopX++;
else if(board[i].charAt(i)=='O') leftTopO++;
if(board[N-1-i].charAt(i)=='X') rightTopX++;
else if(board[N-1-i].charAt(i)=='O') rightTopO++;
}
if(leftTopO==N||rightTopO==N) return "O";
else if(leftTopX==N||rightTopX==N) return "X";
else{
return hasBlank?"Pending":"Draw";
}
}
}
跳跃游戏
简单的思考:暴力解法,声明一个boolean数组reachead记录该元素是否可达,遍历该数组更新reached,最终判断目的地是否可达
更好的解法:声明一个可达的最大值,遍历数组的同时不断更新该最大值,最终看值是否超过目的地
class Solution {
public boolean canJump(int[] nums) {
int n = nums.length;
int arrivemost = 0;
for(int i=0;i<n;i++){
if(arrivemost>=i)
arrivemost = Math.max(arrivemost,i+nums[i]);
if(arrivemost>=n-1){
return true;
}
}
return false;
}
}
旋转图像
- 借助辅助数组
寻找到翻转的规律
class Solution {
public void rotate(int[][] matrix) {
int N = matrix.length;
int[][] matrix_new = new int[N][N];
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
matrix_new[j][N-1-i]=matrix[i][j];
}
}
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
matrix[i][j] = matrix_new[i][j];
}
}
}
}
- 标准原地旋转
最贴近大脑思考的一种解法,很容易想到,但是实现有点困难,思路大概是外圈旋转的思路复用到内层,
class Solution {
public void rotate(int[][] matrix) {
int n = matrix.length;
int s1_i = 0;
int s1_j = 0;
while (n > 1) {
int s2_i = s1_i;
int s2_j = s1_j+n-1;
int s3_i = s1_i+n-1;
int s3_j = s1_j+n-1;
int s4_i = s1_i+n-1;
int s4_j = s1_j;
for (int move = 0; move<=n-2; ++move) {
int p1_i = s1_i + 0;
int p1_j = s1_j + move;
int p2_i = s2_i + move;
int p2_j = s2_j + 0;
int p3_i = s3_i + 0;
int p3_j = s3_j - move;
int p4_i = s4_i - move;
int p4_j = s4_j + 0;
swap4(matrix, p1_i, p1_j, p2_i, p2_j, p3_i, p3_j, p4_i, p4_j);
}
s1_i++;
s1_j++;
n-=2;
}
} }
private void swap4(int[][] a, int i1, int j1, int i2, int j2, int i3, int j3, int i4, int j4) {
int tmp = a[i1][j1];
a[i1][j1] = a[i4][j4];
a[i4][j4] = a[i3][j3];
a[i3][j3] = a[i2][j2];
a[i2][j2] = tmp;
}
螺旋矩阵
不断地模拟循环矩阵的过程,注意边界的处理
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
List<Integer> order = new ArrayList<Integer>();
int left = 0;
int right = n-1;
int top = 0;
int bottom = m-1;
//不断地循环螺旋矩阵的过程
while(left<=right&&top<=bottom){
for(int j=left;j<=right;j++){
order.add(matrix[top][j]);
}
for(int i=top+1;i<=bottom;i++){
order.add(matrix[i][right]);
}
if(top!=bottom){
for(int j=right-1;j >= left;j--){
order.add(matrix[bottom][j]);
}
}
if(left!=right){
for(int i=bottom-1;i>= top+1;i--){
order.add(matrix[i][left]);
}
}
left++;
right--;
top++;
bottom--;
}
return order;
}
}
搜索二维矩阵()
思路:寻找到一个起点一层层剥离,比如说这道题找到的是右上角的点0,w-1。如果目标点大于该点,因为该行的数据中该点是最大值故i++,表示剥离这一行;若目标点值小于该点,因为该列的数据中该点是最小值故j–,表示剥离该列,如从循环便能找到目标点是否在矩阵里。
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int h=matrix.length; //h表示矩阵的行数(高度)
int w=matrix[0].length; //w表示矩阵的列数(宽度)
//寻找一个始发点作为搜索的起始点 一般是矩阵的右上角
int i=0;
int j=w-1;
while(i<=h-1&&j>=0){
if(matrix[i][j]==target){
return true;
}
if(matrix[i][j]<target){
i++;
continue;
}
if(matrix[i][j]>target){
j--;
continue;
}
}
return false;
}
}