這次只有兩題,也不是我不想放三題,我目前刷的那部分就剩這兩題了,而且作爲壓軸,也不會簡單。
看題目就嚇人。
哦,原來是中等難度啊。
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、總結
這兩題做完,映射表的使用是得刻骨銘心了。
哈希散列表嘛,還得再看看。
不過數組這一套做下來,我深刻認識到,在寫代碼之前,得把思維導圖畫出來!!!