赞
踩
只要统计战舰头的个数即可,每个战舰头的左边和上面一定是 ‘ . ’ ,只要判断这个条件,把所有的战舰头统计一下就行了
一次扫描并且额外空间O(1)
class Solution {
public:
int countBattleships(vector<vector<char>>& board) {
int count = 0;
for(int i = 0; i < board.size(); i++){
for(int j = 0; j < board[0].size(); j++){
if(board[i][j] == 'X' && (i == 0 || board[i - 1][j] == '.')
&& (j == 0 || board[i][j - 1] == '.')){
count ++;
}
}
}
return count;
}
};
看了题解好像没有比这个更优的解法了,就没重新改进了-_-
自己马上想到的就是直接另外开一个数组,然后一个一个赋值
时间和空间复杂度都是O(N)
class Solution {
public:
void rotate(vector<int>& nums, int k) {
vector<int> res = nums;
for(int i = 0; i < nums.size(); i++){
nums[(i + k) % nums.size()] = res[i];
}
}
};
要求用三种方法…
然后看了题解
数组翻转
当我们将数组的元素向右移动 k 次后,尾部 k mod n 个元素会移动至数组头部,其余元素向后移动。
该方法为数组的翻转:
class Solution { public: void reverse(vector<int>& nums, int start, int end){ while(start < end){ swap(nums[start], nums[end]); start ++; end --; } } void rotate(vector<int>& nums, int k) { k = k % nums.size();//因为没有说k会小于nums.size() reverse(nums, 0, nums.size() - 1); reverse(nums, 0, k - 1); reverse(nums, k, nums.size() - 1); } };
这种方法所有的元素都被遍历到两次,O(2N) = O(N),
空间复杂度O(1)
3 环形旋转
要注意如果nums.size()刚好是k的整数倍的话,会出现死循环,因此可以另外设置一个visit数组,如果已经访问过,就往后移动一位继续替换,但是这种情况还是要另外开一个n的数组,还不如直接用第一种做法简单直接
这是最优的解法(目前),只要遍历一次数组,并且没有额外的空间开销
上一种做法是每次cur和next移动,把移动后的互相替换,但是这个是每次都是用i位置的替换,直到下一次替换到i,完成一轮,总共需要n和k的最大公约数轮
class Solution { public: void rotate(vector<int>& nums, int k) { int n = nums.size(); k = k % n; int count = gcd(n, k);//最大公约数 for(int i = 0; i < count; i++){ int cur = i; int first = nums[i]; do{ int next = (cur + k) % n; swap(first, nums[next]); cur = next; }while(i != cur); } } };
这些用户是魔鬼吗??
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。