数组
一、刷题
1、53. 最大子数组和
class Solution {
public:
int maxSubArray(vector<int>& nums) {
// int n = nums.size();
// vector<int>sum(n+1);
// int MAX = nums[0];
// sum[0]=0;
// for(int i = 1;i <= nums.size(); i++){
// sum[i] = max(sum[i-1]+nums[i-1], nums[i-1]);
// MAX=max(sum[i], MAX);
// }
// return MAX;
// //贪心算法--更新最大值
// int n=nums.size();
// int res=nums[0];
// for(int i=1;i<n;i++){
// if(nums[i-1]>0)nums[i]+=nums[i-1];
// res=max(res,nums[i]);
// // if(nums[i]>res)res=nums[i];
// }
// return res;
int sum = 0;
int res = nums[0];
for(int i = 0; i < nums.size(); i++) {
if(sum < 0) sum = 0;//sum<0,与谁相加都是负贡献
sum += nums[i];//求最大子数和
res=max(res,sum);//更新最大值:当前最大值与刚求的最大子数和比较,取较大的
}
return res;
}
};
2、27. 移除元素
如果当前元素 i 与移除元素 val 相同,那么跳过该元素。
如果当前元素 i 与移除元素 val 不同,那么我们将其放到下标 left的位置,并让 left 自增右移。
最终得到的 left 即是答案。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
// int right = nums.size()-1;
// int left = 0;
// while(left <= right){
// if(nums[left] == val){
// nums[left] = nums[right--];
// }else{
// left++;
// }
// }
// return left;
int n = nums.size();
int left = 0;
for(int i=0; i<n; i++){
if(nums[i] != val){
nums[left++] = nums[i];
}
}
return left;
}
};
3、生成元素不重复的随机数组
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void swap(int &a, int &b){
a = a^b;
b = a^b;
a = a^b;
}
int main()
{
srand((int)time(0)); //用当前时间作为随机种子
int a[5] = {0};
for(int i=0; i<5; ++i) a[i]=i;
for(int i=4; i>=1; --i) swap(a[i], a[rand()%i]); //随机交换下标
for(int i=0; i<5; i++){
printf("%d\n", a[i]);
}
getchar();
return 0;
}
/*
用C语言程序输出指定范围的不重复的随机数
本程序以输出50个范围为1-50的不重复的随机数为例
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int a[50],i=0,j,r;
srand((int)time(0)); //用当前时间作为随机种子
while(i<50)
{
r=rand() % 50 + 1; //生成一个1-50的随机数
for(j=i;j>=0;j--)
{
if(r==a[j]) //与之前已存的随机数比较
break;
}
if(j<0) //没有重复即保存到数组中
{
a[i]=r;
i++;
}
}
while (i--) //从数组中输出这50个范围在1-50的不重复的随机数
{
printf("rand_num[%d] = %d\n",50-i,a[i]);
// getchar();
}
system("pause");
return 0;
}
4、剑指 Offer II 079. 所有子集
如果一个集合的元素个数为n,则每个元素都有存在或不存在两种情况,n个元素一共2^n种情况,因此元素个数为n的集合一共有2的n次方个子集。
利用二进制的思想 如 0110 1001,0表示该数组位置不选,1表示选中。加入数组为[1,2,3,4] 0110就表示[2,3] 1001表示[1,4]
求arr[4]={1,2,3,4}的所有子集
用for(i=0;i<16;i++)遍历这16种情况,每一个i的值,例如i=3,则二进制数为0011,我们从右边往左遍历(最右边为低位0),即0011的下标序列为3210,从右往左遍历,即输出arr[0],arr[1]。那么16个数的二进制:0000,0001…1111对应了16种输出的情况,即输出的子集。假如i=7时,j=i=7,那么此时j=0111,我们对应输出arr[0],arr[1],arr[2],这个过程在while循环中完成。
1<<1 结果为2(a=a<<m表示a乘以2^m)
2>>1结果为0(a>>=m表示a/2^m)
#include<stdio.h>
#include<stdlib.h>
//求集合的所有子集 整形数组arr,arr长度为len
void AllSubsets(int *arr,int len)
{
int i,j,k;
int num=1<<len;//1左移len位,即乘以2^len,num=2^len个子集
for(i=0;i<num;i++)
{
j=i;
k=0;
printf("{");
while(j)
{
//j的二进制与0001按位与,输出不为0则打印
//和0001按位与意思是判断最右边是否为1
if(j&1)
{
printf("%d",arr[k]);
}
j>>=1;//j右移一位,即/2,0011变为0001,意思是从右往左遍历每一位,为1则输出为0则不输出
k++;
}
printf("}\n");
}
}
int main()
{
int b=0;
scanf("%d",&b);
int arr[b];
for(int i=0;i<b;i++)
{
scanf("%d",&arr[i]);
}
int len=sizeof(arr)/sizeof(arr[0]);
AllSubsets(arr,len);
}
class Solution {
public:
vector<int> t;
vector<vector<int>> ans;
vector<vector<int>> subsets(vector<int>& nums) {
int n = nums.size();
for (int mask = 0; mask < (1 << n); ++mask) {
t.clear();
for (int i = 0; i < n; ++i) {
if (mask & (1 << i)) {
t.push_back(nums[i]);
}
}
ans.push_back(t);
}
return ans;
}
};