日练三题,冰冻三尺非一日之寒。
今日题目:1、每个节点加上next right指针;2、完全平方数;3、旋转矩阵;4、旋转矩阵II。
今日摘录:
也许每一个男子全都有过这样的两个女人,至少两个.
娶了红玫瑰,久而久之,红的变了墙上的一抹蚊子血,白的还是“床前明月光”;
娶了白玫瑰,白的便是衣服上的一粒饭粘子,红的却是心口上的一颗朱砂痣。 ——《红玫瑰与白玫瑰》
116. Populating Next Right Pointers in Each Node | Difficulty: Medium
Given a binary tree
struct TreeLinkNode {
TreeLinkNode *left;
TreeLinkNode *right;
TreeLinkNode *next;
}
Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.
Initially, all next pointers are set to NULL.
Note:
You may only use constant extra space.
You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent has two children).
For example,
Given the following perfect binary tree,
1
/ \
2 3
/ \ / \
4 5 6 7
After calling your function, the tree should look like:
1 -> NULL
/ \
2 -> 3 -> NULL
/ \ / \
4->5->6->7 -> NULL
题意:给满二叉树增加一个同层之间指向下一个节点的指针,如果不存在同层之间的下一个节点那么就置为NULL。
思路:
1、题目说了是满二叉树,这个限制下有哪些节点是没有下一个节点的呢?很显然是每一层的最后一个节点,从序号上来看是0 2 6 14 ,也就是2^n-2。但是满二叉树好像也没特别方便的方法去遍历指定序号的节点,那最好就是自己在纸上去模拟一下,然后去写代码。
大概写下做法,用两个节点,一个pre代表每一层的第一个节点,cur代表在同层之间建立指向关系的节点。根节点是不需要操作的,那么现在从第二层进行操作就可以了,怎么样去对第二层的两个节点之间建立指向关系呢?在根节点的时候判断是否有左节点,如果有的话将左节点指向右节点,同时判断根节点的next是否为空,如果不为空说明根节点有同层节点的存在,那么需要将根节点的右节点和根节点的下一个节点的左节点建立连接,同时根节点切换到它的next节点,知道next节点是空为止。
理清逻辑之后代码就很容易实现了。
/**
* Definition for binary tree with next pointer.
* struct TreeLinkNode {
* int val;
* TreeLinkNode *left, *right, *next;
* TreeLinkNode(int x) : val(x), left(NULL), right(NULL), next(NULL) {}
* };
*/
class Solution {
public:
void connect(TreeLinkNode *root) {
if(!root) return ;
TreeLinkNode* pre=root;
TreeLinkNode* cur=NULL;
while(pre->left)
{
cur=pre;
while(cur)
{
if(cur->left) cur->left->next = cur->right;
if(cur->next) cur->right->next = cur->next->left;
cur = cur->next;
}
pre = pre->left;
}
}
};
结果:24ms
367. Valid Perfect Square | Difficulty: Medium
Given a positive integer num, write a function which returns True if num is a perfect square else False.
Note: Do not use any built-in library function such as sqrt.
Example 1:
Input: 16
Returns: True
Example 2:
Input: 14
Returns: False
题意:如何判断一个数是否是完全平方数,不允许用自带的sqrt等函数。
思路:
1、二分的思想,一个比较直观的写法
class Solution {
public:
bool isPerfectSquare(int num) {
int l=1,r = num;
while(l<=r)
{
long mid=(l+r)/2;
if(mid*mid==num) return true;
else if (mid*mid>num) r=mid-1;
else l=mid+1;
}
return false;
}
};
结果:2ms
同样的思想,另外一种更神奇的写法
class Solution {
public:
bool isPerfectSquare(int num) {
long r = num;
while(r*r>num)
{
r = (r+num/r)/2;
}
return r*r==num;
}
};
结果:0ms
2、不妨从完全平方数的规律去思考解法
1 = 1
4 = 1 + 3
9 = 1 + 3 + 5
16 = 1 + 3 + 5 + 7
25 = 1 + 3 + 5 + 7 + 9
36 = 1 + 3 + 5 + 7 + 9 + 11
….
所以 1+3+…+(2n-1) = (2n-1 + 1)n/2 = n^2
那么每次判断一个数是不是完全平方,我们可以从1开始减,每次减的数字加2,减到最后判断结果是否为0即可。
class Solution {
public:
bool isPerfectSquare(int num) {
if(num<=0) return false;
int i=1;
while(num>0)
{
num-=i;
i+=2;
}
return num==0;
}
};
结果:0ms
54. Spiral Matrix | Difficulty: Medium
Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.
For example,
Given the following matrix:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
You should return [1,2,3,6,9,8,7,4,5].
题意:给一个m行n列的矩阵,顺时针打印其中元素的值。
思路:
1、m行n列,从外圈到里圈去遍历,一圈一圈遍历,首先需要知道要遍历多少圈,这是由m和n中的较小者决定的,min(m,n)/2就是要遍历的圈数,那么我们在遍历每圈的时候需要什么参数呢?需要矩阵matrix、起始位置(start,start),矩形的行数,矩形的列数,每遍历完一圈就start+1。
至于每圈可以看成向右、向下、向左、向上四个步骤,每个步骤都需要判断是否执行,感觉不太好说清楚,最好自己在纸上画画,才能考虑清楚所有边界,花了半个小时终于理清了。
这是剑指offer第20题书上所述。
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> res;
int start = 0;
int rows = matrix.size();
if(rows<=0) return res;
int cols = matrix[0].size();
while(rows>start*2&&cols>start*2)
{
printCircle(matrix,rows,cols,start,res);
start++;
}
return res;
}
void printCircle(vector<vector<int>>matrix,int rows,int cols,int start,vector<int>&res)
{
int x_max = cols-1-start,y_max=rows-1-start;
//向右
for(int i=start;i<=x_max;i++)
res.push_back(matrix[start][i]);
//向下
if(y_max-start>0)
{
for(int i=start+1;i<=y_max;i++)
res.push_back(matrix[i][x_max]);
}
//向左
if(x_max-start>0&&y_max-start>0)
{
for(int i=x_max-1;i>=start;i--)
res.push_back(matrix[y_max][i]);
}
//向上
if(x_max-start>0&&y_max-start>1)
{
for(int i=y_max-1;i>start;i--)
res.push_back(matrix[i][start]);
}
}
};
结果:0ms
2、还有一种很巧妙的方法
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> res;
if(matrix.size()<=0) return res;
int rowBegin = 0;
int rowEnd = matrix.size()-1;
int colBegin = 0;
int colEnd = matrix[0].size()-1;
while (colBegin <= rowEnd && colBegin <= colEnd)
{
//right
for(int i=rowBegin;i<=colEnd;i++)
res.push_back(matrix[rowBegin][i]);
rowBegin++;
//down
for(int i=rowBegin;i<=rowEnd;i++)
res.push_back(matrix[i][colEnd]);
colEnd--;
//left
if(rowEnd>=rowBegin)
{
for(int i=colEnd;i>=colBegin;i--)
res.push_back(matrix[rowEnd][i]);
}
rowEnd--;
//up
if(colEnd>=colBegin)
{
for(int i=rowEnd;i>=rowBegin;i--)
res.push_back(matrix[i][colBegin]);
}
colBegin++;
}
return res;
}
};
结果:0ms
59. Spiral Matrix II | Difficulty: Medium
Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order.
For example,
Given n = 3,
You should return the following matrix:
[
[ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ]
]
题意:给定一个整数,将1-n^2之间的数按照顺时针顺序存入矩阵中。
思路:
与上题旋转矩阵I 类似,只是改成先初始化一个n*n的向量,每个元素置为0,然后再遍历一次向量,逐一赋值,最后返回这个二维向量。
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> matrix(n,vector<int>(n,0));
if(n<=0) return matrix;
int rowBegin = 0;
int rowEnd = matrix.size()-1;
int colBegin = 0;
int colEnd = matrix[0].size()-1;
int Cnt=1;
cout<<rowEnd<<endl;
cout<<colEnd<<endl;
while (colBegin <= rowEnd && colBegin <= colEnd)
{
//right
for(int i=rowBegin;i<=colEnd;i++)
{
matrix[rowBegin][i] = Cnt;
Cnt++;
}
rowBegin++;
//down
for(int i=rowBegin;i<=rowEnd;i++)
{
matrix[i][colEnd] = Cnt;
Cnt++;
}
colEnd--;
//left
if(rowEnd>=rowBegin)
{
for(int i=colEnd;i>=colBegin;i--)
{
matrix[rowEnd][i] = Cnt;
Cnt++;
}
}
rowEnd--;
//up
if(colEnd>=colBegin)
{
for(int i=rowEnd;i>=rowBegin;i--)
{
matrix[i][colBegin] = Cnt;
Cnt++;
}
}
colBegin++;
}
return matrix;
}
};
结果:4ms
2、但是因为这里和之前的遍历不同,本题已经限制了是方阵,这样就很好办了。直接循环就能搞定
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n,vector<int>(n));
if(n<=0) return res;
int k = 1,i=0;
while(k<=n*n)
{
int j=i;
//right
while(j<n-i)
res[i][j++] = k++;
j=i+1;
//down
while(j<n-i)
res[j++][n-1-i] =k++;
j=n-i-2;
//left
while(j>=i)
res[n-1-i][j--]=k++;
j=n-i-2;
//up
while(j>i)
res[j--][i] = k++;
i++;
}
return res;
}
};
结果:4ms