力扣刷题笔记(四)

这次只有两题,也不是我不想放三题,我目前刷的那部分就剩这两题了,而且作为压轴,也不会简单。
看题目就吓人。

哦,原来是中等难度啊。

1、题目1

判断一个 9x9 的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可。

数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

数独部分空格内已填入了数字,空白格用 ‘.’ 表示。

示例 1:

输入:
[
[“5”,“3”,".",".",“7”,".",".",".","."],
[“6”,".",".",“1”,“9”,“5”,".",".","."],
[".",“9”,“8”,".",".",".",".",“6”,"."],
[“8”,".",".",".",“6”,".",".",".",“3”],
[“4”,".",".",“8”,".",“3”,".",".",“1”],
[“7”,".",".",".",“2”,".",".",".",“6”],
[".",“6”,".",".",".",".",“2”,“8”,"."],
[".",".",".",“4”,“1”,“9”,".",".",“5”],
[".",".",".",".",“8”,".",".",“7”,“9”]
]
输出: true
示例 2:

输入:
[
[“8”,“3”,".",".",“7”,".",".",".","."],
[“6”,".",".",“1”,“9”,“5”,".",".","."],
[".",“9”,“8”,".",".",".",".",“6”,"."],
[“8”,".",".",".",“6”,".",".",".",“3”],
[“4”,".",".",“8”,".",“3”,".",".",“1”],
[“7”,".",".",".",“2”,".",".",".",“6”],
[".",“6”,".",".",".",".",“2”,“8”,"."],
[".",".",".",“4”,“1”,“9”,".",".",“5”],
[".",".",".",".",“8”,".",".",“7”,“9”]
]
输出: false
解释: 除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。
但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。
说明:

一个有效的数独(部分已被填充)不一定是可解的。
只需要根据以上规则,验证已经填入的数字是否有效即可。
给定数独序列只包含数字 1-9 和字符 ‘.’ 。
给定数独永远是 9x9 形式的。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/valid-sudoku
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


2、题目2

给定一个 n × n 的二维矩阵表示一个图像。

将图像顺时针旋转 90 度。

说明:

你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。

示例 1:

给定 matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],

原地旋转输入矩阵,使其变为:
[
[7,4,1],
[8,5,2],
[9,6,3]
]
示例 2:

给定 matrix =
[
[ 5, 1, 9,11],
[ 2, 4, 8,10],
[13, 3, 6, 7],
[15,14,12,16]
],

原地旋转输入矩阵,使其变为:
[
[15,13, 2, 5],
[14, 3, 4, 1],
[12, 6, 8, 9],
[16, 7,10,11]
]

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/rotate-image
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


3、我的题解(1)

这题,我做的还是比较满意的。
怎么说呢,最近总是有一个解题方法在我眼前出现,用map键值对来记录遍历的数据,于是我就抓住了这个解法,自主实现!

还别说,真好用。我的好兄弟他去暴力破解了,果然中午崩溃的跟我说他放弃了。

来看一下我的思维导图:

在这里插入图片描述


#include<vector>
#include<map>
#include<iostream>
#include<algorithm>

using namespace std;

bool isValidSudoku(vector<vector<char> >& board)
{
    char ai;
    //创建键值对表及其初始化
    map<char, int> ID_Num;
    ID_Num['1'] = 0;
    ID_Num['2'] = 0;
    ID_Num['3'] = 0;
    ID_Num['4'] = 0;
    ID_Num['5'] = 0;
    ID_Num['6'] = 0;
    ID_Num['7'] = 0;
    ID_Num['8'] = 0;
    ID_Num['9'] = 0;

    map<char, int>::iterator it;

    //将横的先输入
    for (int i = 0; i < 9; i++)
    {
        for (int j = 0; j < 9; j++)
        {
            ai = board[i].at(j);
            if (ai >= 49 && ai <= 57)
            {
                ID_Num[ai]++;
            }
        }
        //走过一轮,该遍历map了
        for (it = ID_Num.begin(); it != ID_Num.end(); it++)
        {
            if (it->second == 1)
                it->second = 0;
            else if (it->second > 1)
                return false;
        }
    }

    //接下来竖着走
    for (int i = 0; i < 9; i++)
    {
        for (int j = 0; j < 9; j++)
        {
            ai = board[j].at(i);
            if (ai >= 49 && ai <= 57)
            {
                ID_Num[ai]++;
            }
        }
        //走过一轮,该遍历map了
        for (it = ID_Num.begin(); it != ID_Num.end(); it++)
        {
            if (it->second == 1)
                it->second = 0;
            else if (it->second > 1)
                return false;
        }
    }

    //接下来走方块
    for (int i = 0; i < 9; i += 3)
    {
        for (int j = 0; j < 9; j++)
        {
            ai = board[i].at(j);
            if (ai >= 49 && ai <= 57)
            {
                ID_Num[ai]++;
            }

            ai = board[i + 1].at(j);
            if (ai >= 49 && ai <= 57)
            {
                ID_Num[ai]++;
            }

            ai = board[i + 2].at(j);
            if (ai >= 49 && ai <= 57)
            {
                ID_Num[ai]++;
            }

            if (j == 2 || j == 5 || j == 8)
            {
                //走过一轮,该遍历map了
                for (it = ID_Num.begin(); it != ID_Num.end(); it++)
                {
                    if (it->second == 1)
                        it->second = 0;
                    else if (it->second > 1)
                        return false;
                }
            }
        }
    }
    return true;
}

int main()
{
    vector<vector<char> > vec1 = { {'5','3','.','.','7','.','.','.','.' }, { '6','.', '.','1','9','5','.','.','.' }, {'.','9','8','.','.','.','.','6','.'},{'8','.','.','.','6','.','.','.','3'},{'4','.','.','8','.','3','.','.','1' }, { '7','.','.','.','2','.','.','.','6' }, { '.','6','.','.','.','.','2','8','.' }, { '.', '.', '.', '4', '1', '9', '.', '.', '5'
}, { '.','.','.','.','8','.','.','7','9' }};

   
    int b = isValidSudoku(vec1);
    cout << b << endl;
};

//测试集我就放这里了

这里要提一点,用map的 at() 进行操作时,如果键值不存在,会自动插入一个键值。

其实里面很多操作都是重复的,可以单独提出来当函数。

4、我的题解(2)

本来呢,我是想用hashtable哈希表的,但是呢,弄了仨儿小时找不到资料,所以决定换条路走。

来看我的画图水平啊。
在这里插入图片描述

还挺形象生动吧。

#include<iostream>
#include<vector>

using namespace std;

void rotate(vector<vector<int>>& matrix) 
{
	int sz = matrix[0].size();
	int cycle_num = sz/2;	//圈数,sz为奇数则最后一圈不用转

//	vector<int> glob(sz);	//原来这个才是内鬼
	vector<int> glob;
	
	int j;	//下面转圈的核心

	//这里是循环主体
	for (int i = 0; i < cycle_num; i++)
	{

		//将当前圈的首尾记录
		int low = i;
		int hight = sz - i - 1;

		//将上面那一行先弄上去
//		glob.insert(glob.begin(),matrix[i].at(i),matrix[low].at(hight));	
		int gn = hight+1;	//对于处理内圈,这行不能写成size
		while (gn)
		{
			glob.push_back(matrix[low][gn-1]);
			gn--;
		}

		//抓住定量,转一圈
		for (j = 0;low<hight;low++,j++)
		{
			//用左边那一列填上上面那一行
			matrix[i].at(hight-j) = matrix[low].at(i);
			//再用下面那一行实时填上左边那一列
			matrix[low].at(i) = matrix[hight].at(low);
			//然后把右边那一列一到下面
			matrix[hight].at(low) = matrix[hight-j].at(hight);
			//最后把通用容器里面的东西放到右边那一列
			matrix[hight - j].at(hight) = glob.at(j);
		}

		//一圈之后,清空通用容器,准备接下一圈
		glob.clear();
	}
}

int main()
{
	vector<vector<int>> vec1 = { {5, 1, 9, 11}, {2, 4, 8, 10}, {13, 3, 6, 7}, {5, 14, 12, 16} };
	//vector<vector<int>> vec1 = { { 4, 8}, {3, 6} };
	rotate(vec1);

	return 0;
}

//测试集也给你放这里了,不过遍历打印自己弄

5、官方题解(1)

方法:一次迭代
如何确保行 / 列 / 子数独中没有重复项?
可以利用 value -> count 哈希映射来跟踪所有已经遇到的值。

现在,我们完成了这个算法的所有准备工作:

遍历数独。
检查看到每个单元格值是否已经在当前的行 // 子数独中出现过:
	如果出现重复,返回 false。
	如果没有,则保留此值以进行进一步跟踪。
返回 true。
class Solution {
  public boolean isValidSudoku(char[][] board) {
    // init data
    HashMap<Integer, Integer> [] rows = new HashMap[9];
    HashMap<Integer, Integer> [] columns = new HashMap[9];
    HashMap<Integer, Integer> [] boxes = new HashMap[9];
    for (int i = 0; i < 9; i++) {
      rows[i] = new HashMap<Integer, Integer>();
      columns[i] = new HashMap<Integer, Integer>();
      boxes[i] = new HashMap<Integer, Integer>();
    }

    // validate a board
    for (int i = 0; i < 9; i++) {
      for (int j = 0; j < 9; j++) {
        char num = board[i][j];
        if (num != '.') {
          int n = (int)num;
          int box_index = (i / 3 ) * 3 + j / 3;

          // keep the current cell value
          rows[i].put(n, rows[i].getOrDefault(n, 0) + 1);
          columns[j].put(n, columns[j].getOrDefault(n, 0) + 1);
          boxes[box_index].put(n, boxes[box_index].getOrDefault(n, 0) + 1);

          // check if this value has been already seen before
          if (rows[i].get(n) > 1 || columns[j].get(n) > 1 || boxes[box_index].get(n) > 1)
            return false;
        }
      }
    }

    return true;
  }
}

> 作者:LeetCode
> 链接:https://leetcode-cn.com/problems/valid-sudoku/solution/you-xiao-de-shu-du-by-leetcode/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

时间复杂度:O(1),因为我们只对 81 个单元格进行了一次迭代。
空间复杂度:O(1)。

方法是很不错的

然后评论区里又有大佬说直接用数组不香吗?
我觉得吧,至少我掌握了用映射表这个方法,而且如果这个数组大起来的话,孰优孰劣真不好说哦,数组坑定得淘汰了。


6、官方题解(2)

在这里插入图片描述

还真别说,这个图画的真不错。

那这个方法就不说了,跟我的一样。来看另一个,大佬们都说妙的。

方法 1 :转置加翻转
最直接的想法是先转置矩阵,然后翻转每一行。这个简单的方法已经能达到最优的时间复杂度O(N^2)

反正我是没直接想到。

class Solution {
  public void rotate(int[][] matrix) {
    int n = matrix.length;

    // transpose matrix
    for (int i = 0; i < n; i++) {
      for (int j = i; j < n; j++) {
        int tmp = matrix[j][i];
        matrix[j][i] = matrix[i][j];
        matrix[i][j] = tmp;
      }
    }
    // reverse each row
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n / 2; j++) {
        int tmp = matrix[i][j];
        matrix[i][j] = matrix[i][n - j - 1];
        matrix[i][n - j - 1] = tmp;
      }
    }
  }
}

> 作者:LeetCode
> 链接:https://leetcode-cn.com/problems/rotate-image/solution/xuan-zhuan-tu-xiang-by-leetcode/
> 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


7、总结

这两题做完,映射表的使用是得刻骨铭心了。
哈希散列表嘛,还得再看看。

不过数组这一套做下来,我深刻认识到,在写代码之前,得把思维导图画出来!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章