力扣刷題筆記(四)

這次只有兩題,也不是我不想放三題,我目前刷的那部分就剩這兩題了,而且作爲壓軸,也不會簡單。
看題目就嚇人。

哦,原來是中等難度啊。

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、總結

這兩題做完,映射表的使用是得刻骨銘心了。
哈希散列表嘛,還得再看看。

不過數組這一套做下來,我深刻認識到,在寫代碼之前,得把思維導圖畫出來!!!

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