该题的目的是对已知矩阵进行转置,由于矩阵的行数和列数可能不相等,对于一个m行n列的矩阵,利用vector创建一个n行m列的空矩阵res,进行赋值操作,res[j][i] = matrix[i][j]。
class Solution {
public:
vector<vector<int>> transpose(vector<vector<int>>& matrix) {
int m = matrix.size(), n = matrix[0].size();
vector<vector<int>> res(n, vector<int>(m));
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
res[j][i] = matrix[i][j];
}
}
return res;
}
};
摩尔投票法:
在网上看到了一个形象的比喻,多个候选人要选举总统,如果其中一个人获得选票比其他人加起来的还多,那么即使进行一对一的比拼,最后剩下的还是这个人。
算法步骤:
I. 遍历数组元素,从第一个元素开始,计数器初始设置为0,st设置为数组第一个元素
II.遇到与st相同的元素时,count加1,否则,count减一。若count=0时,st更换为现在的元素
III.最后重新遍历一遍数组,看st的数量是否超过数组元素的一半,若超过一半,则返回该元素,否则返回-1.
class Solution {
public:
int majorityElement(vector<int>& nums) {
int n = nums.size();
if(n == 0) return -1;
int st = nums[0], count = 0;
for(int i = 0; i < n; i++){
if(nums[i] == st){
count++;
}
else{
count--;
if(count <= 0){
st = nums[i];
count = 1;
}
}
}
count = 0;
for(int i = 0; i < n; i++){
if(st == nums[i]) count++;
}
if(count > n/2) return st;
else return -1;
}
};
排序方法:
将数组从小到大排序,若某个元素数量超过数组元素个数一半,数组最中间的元素一定是该元素。
class Solution {
public:
int majorityElement(vector<int>& nums) {
int n = nums.size();
if(n == 0) return -1;
sort(nums.begin(), nums.end()); //对数组从小到大排序
int mid = nums[n/2];
int count = 0; //设置计数器
for(int i = 0; i < n; i++){
if(mid == nums[i]) count++;
}
if(count > n/2) return mid;
else return -1;
}
};
暴力算法
先将数组元素都平方,然后将数组重新排序
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int n = nums.size();
for(int i = 0; i < n; i++){
nums[i] = nums[i] * nums[i];
}
sort(nums.begin(), nums.end());
return nums;
}
};
双指针
题目条件给出数组是非递减顺序排列的,对于正数来说,平方之后顺序不变,对于负数来说,平方之后顺序反转,所以平方后的最大值出现在数组开头或者结尾,最小值出现在数组中间。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int n = nums.size()-1;
int i, j;
vector<int> ans(nums.size(), 0);
for(i=0, j=nums.size()-1; i <= j;){
if(nums[i]*nums[i] < nums[j]*nums[j]){
ans[n--] = nums[j] * nums[j];
j--;
}
else{
ans[n--] = nums[i] * nums[i];
i++;
}
}
return ans;
}
};
最大值可能出现的情况只有两种,一种是三个全是正数,即数组最大的三个正数,另一种是两个负数一个正数,最小的两个负数和最大的一个正数
排序法
class Solution {
public:
int maximumProduct(vector<int>& nums) {
sort(nums.begin(), nums.end());
int n = nums.size();
return max(nums[0]*nums[1]*nums[n-1], nums[n-3]*nums[n-2]*nums[n-1]);
}
};
非排序法
是要找到最大的三个值和最小的两个值就可以了
class Solution {
public:
int maximumProduct(vector<int>& nums) {
int n = nums.size();
int max1 = -1000, max2 = -1000, max3 = -1000; //第一、第二、第三大的数
int min1 = 1000, min2 = 1000; //第一、第二小的数
for(int i = 0; i < n; i++){
if(nums[i] >= max1){ //大于最大的数
max3 = max2; max2 = max1; max1 = nums[i];
}
else if(nums[i] >= max2){ //在max1和max2之间
max3 = max2; max2 = nums[i];
}
else if(nums[i] >= max3){ //在max2和max3之间
max3 = nums[i];
}
if(nums[i] <= min1){ //比最小值还小
min2 = min1; min1 = nums[i];
}
else if(nums[i] <= min2){ //在min1和min2之间
min2 = nums[i];
}
}
return max(min1*min2*max1, max3*max2*max1);
}
};
哈希表HashSet,HashSet继承于set类,set类的元素都是唯一的。
算法步骤:
i. 构造一个哈希表set,让哈希表的长度始终为k
ii. 遍历整个数组,看遍历的元素是否已经存在于set集合中了,若在集合中,则返回true,若没在集合中,则将该元素加入哈希表,若哈希表的长度超过k,则将最先加入的元素移除
解法说明:https://leetcode-cn.com/problems/contains-duplicate-ii/solution/hua-jie-suan-fa-219-cun-zai-zhong-fu-yuan-su-ii-by/
class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
HashSet<Integer> set = new HashSet<>();
for(int i = 0; i < nums.length; i++){
if(set.contains(nums[i])) return true;
set.add(nums[i]);
if(set.size() > k){
set.remove(nums[i-k]);
}
}
return false;
}
}
代码注意事项
i.while(i < n && nums[i-1]+1 == nums[i])要先写i
ii. c++中存在string类,将数字转换成字符可以使用to_string函数,在后面添加元素可以用append函数
class Solution {
public:
vector<string> summaryRanges(vector<int>& nums) {
int i = 0;
vector<string> ret;
int n = nums.size();
while(i < n){
int low = i;
i++;
while(i < n && nums[i-1]+1 == nums[i]){
i++;
}
int high = i-1;
string temp = to_string(nums[low]);
if(low < high){ //证明存在一个区间
temp.append("->");
temp.append(to_string(nums[high]));
}
ret.push_back(temp);
}
return ret;
}
};
(2)题解:
暴力枚举
class Solution {
public:
vector twoSum(vector& nums, int target) {
int n = nums.size();
for(int i = 0; i < n; i++){
int j = i+1;
while(j < n){
if(nums[i] + nums[j] == target){
return vector{i, j};
}
else{
j++;
}
}
}
return vector{-1,-1};
}
};
哈希表
class Solution {
public int[] twoSum(int[] nums, int target) {
Map map = new HashMap<>();
for(int i = 0; i < nums.length; i++){
if(map.containsKey(target-nums[i])){
return new int[]{map.get(target-nums[i]), i};
}
map.put(nums[i], i);
}
return new int[]{-1, -1};
}
}
(2)题解:利用数组有序的条件
二分查找
固定第一个值,寻找第二个值的时候用二分查找的方法能缩短查找时间,提高效率。
class Solution {
public:
vector twoSum(vector& numbers, int target) {
int n = numbers.size();
for(int i = 0; i < n; i++){
int low = i+1, high = n-1;
while(low <= high){
int mid = (high-low)/2 + low;
if(numbers[mid] == target - numbers[i]){
return {i+1, mid+1};
}
else if(numbers[mid] > target - numbers[i]){
high = mid - 1;
}
else{
low = mid + 1;
}
}
}
return {-1, -1};
}
};
双指针
初始时将两个指针放在数组两侧,sum为两个指针指向数据之和
若sum==target,则找到唯一解
若sum
class Solution {
public:
vector twoSum(vector& numbers, int target) {
int low = 0, high = numbers.size()-1;
while(low < high){
int sum = numbers[low] + numbers[high];
if(sum == target){
return {low+1, high+1};
}
else if(sum > target){
high--;
}
else{
low++;
}
}
return {-1,-1};
}
};
```