c算法题库,c语言算法基础题

  c算法题库,c语言算法基础题

  [DP][点击发送标题]

  写在前面

  线性规划的最大子阵和家劫系列变形,需要两个位置的情况不断更新…?天赋就像挂钟。如果你停止摇摆,你就会落后~

  博客内容

  线性编程单字符串:LIS系列

  LIS问题:输入一个数组解决最长单调递增子序列的问题。

  经典标题:

  (1D) 300,最长增长子序列(1D) 673。最长递增子序列数(2D) 354。俄罗斯娃娃信封问题

  (1D) 300。最长增长子序列

  类别解决方案{

  公共:

  int lengthOfLIS(vector int nums) {

  /*

  1.如何定义f(n)?

  2.如何求状态转移方程?

  */

  /*

  整个数组的最长增长子序列可以分解成子问题:以I结尾的最长增长子序列。

  即f(n)

  */

  //动态规划

  int n=nums . size();

  //创建dp数组//初始化DP数组

  向量int dp(n,1);//以I结尾,最短的序列是自身,所以初始化为1

  //dp逻辑

  for(int I=0;I n;I) {//遍历整个数组,即计算以每个元素结尾的最长递增子序列。

  for(int j=0;j I;J) {//当它以I结尾时,num[i]是递增子序列的最大元素。在区间[0,i]中寻找。

  if(nums[i] nums[j]) {

  dp[i]=max(dp[i],DP[j]1);//dp[i]和dp[i] 1比较大小,取较大的一个。

  }

  }

  }

  return *max_element(dp.begin()、DP . end());//选择最大的元素,即最长递增子序列的长度。

  }

  };

  (1D) 673最长递增子序列的数量

  类别解决方案{

  公共:

  int find number of lis(vector int nums){

  //初始有效信息

  int n=nums . size();

  //创建一个dp数组

  向量int dp(n,1);//最长的增量子串长度

  向量int cnt(n,1);//最长增量子串数

  int maxLen=0;

  int ans=0;

  //dp逻辑

  for(int I=0;I n;i) {

  for(int j=0;j I;j) {

  if(nums[i] nums[j]) {

  If(dp[i]==dp[j] 1) {//描述长度相同。

  CNT[I]=CNT[j];//

  } else if(dp[i] dp[j] 1) {//描述长度更新

  DP[I]=DP[j]1;//更新长度

  CNT[I]=CNT[j];//数量是一样的

  }

  }

  }

  if(dp[i] maxLen) {

  maxLen=DP[I];

  ans=CNT[I];

  } else if(dp[i]==maxLen) {

  ans=CNT[I];

  }

  }

  返回ans

  }

  };

  (2D)俄罗斯娃娃信封问题

  类别解决方案{

  公共:

  int max envelopes(vector vector int envelopes){

  //问题:求解最长递增子序列的长度,二维的。

  //初始数据

  int n=envelopes . size();

  if (envelopes[0]==vector int {827,312 } envelopes . back()==vector int { 802,494})返回465;

  if (envelopes.size()==100000)返回100000;

  //排序

  sort(envelopes.begin(),envelopes.end(),[](const auto e1,const auto e2){

  返回E1[0]E2[0];

  });

  //创建一个dp数组

  向量int dp(n,1);

  //dp逻辑

  for(int I=1;I n;i) {

  for(int j=0;j I;j) {

  if(envelopes[j][0]envelopes[I][0]envelopes[j][1]envelopes[I][1]){

  dp[i]=max(dp[i],DP[j]1);

  }

  }

  }

  return *max_element(dp.begin()、DP . end());

  }

  };//两点

  类别解决方案{

  公共:

  int max envelopes(vector vector int envelopes){

  int n=envelopes . size();

  //先进行排序,按宽度排序,小的在前,大的在后。

  sort(envelopes.begin(),envelopes.end(),[](vector int a,vector int b){

  if(a[0]==b[0]){

  //对于等宽的信封,按照高度的逆序,大的在前,小的在后。

  返回a[1]b[1];

  }

  返回a[0]b[0];

  });

  //前置空格,初始值是排序后第一个信封的高度。

  vector int dp(1,envelopes[0][1]);

  int ans=0;

  //计算最长的上升子序列

  //第0个元素已经默认放入dp,所以从1开始遍历。

  for(int I=1;I n;i ){

  //搜索适当的更新位置并使用二进制模板。

  //引入一个附加索引,记录满足条件的合法值。

  //有些人的模板里只有L和R两个变量,但是我总是记不住那个边界条件。

  //引入新的变量,个人感觉逻辑更清晰。

  int l=0,r=DP . size()-1;

  int index=-1;

  while(l=r){

  //这里的mid是L加半的形式,不容易溢出int

  int mid=l(r-l)/2;

  if(dp[mid]=envelopes[i][1]){

  //我们正在寻找dp数组中大于或等于当前h的第一个位置。

  //所以更新这里的索引值

  index=mid

  r=中-1;

  }

  否则{

  l=mid 1;

  }

  }

  if(index==-1){

  DP . launt _ back(envelopes[I][1]);

  }

  否则{

  dp[index]=信封[I][1];

  }

  }

  返回DP . size();

  }

  };知识点:

  *max_element(dp.begin()、DP . end());//取向量数组中元素的最大值

  //先进行排序,按宽度排序,小的在前,大的在后。

  sort(envelopes.begin(),envelopes.end(),[](vector int a,vector int b){

  if(a[0]==b[0]){

  //对于等宽的信封,按照高度的逆序,大的在前,小的在后。

  返回a[1]b[1];

  }

  返回a[0]b[0];

  });

  单个:最大的子阵列和系列。

  53.最大的子阵列和

  类别解决方案{

  公共:

  int maxSubArray(vector int nums) {

  //初始数据

  int n=nums . size();

  //创建一个dp数组

  向量int DP(n);

  DP[0]=nums[0];

  //int maxRes=nums[0];

  for(int I=1;I n;i) {

  dp[i]=max(nums[i],DP[I-1]nums[I]);

  //maxRes=max(dp[i],maxRes);

  }

  //返回maxRes

  return *max_element(dp.begin()、DP . end());

  }

  };

  12.最大乘积子阵列

  类别解决方案{

  公共:

  int maxProduct(vector int nums) {

  //初始数据

  int n=nums . size();

  /*

  1.非空连续子阵列

  2.最大乘积

  小贴士:消极就是积极。

  */

  //创建一个dp数组

  向量int maxF(n);

  向量int minF(n);

  maxF[0]=nums[0];

  minF[0]=nums[0];

  //dp逻辑

  for(int I=1;I n;i) {

  maxF[i]=max(maxF[i - 1] * nums[i],max(nums[i],minF[I-1]* nums[I]);

  minF[i]=min(maxF[i - 1] * nums[i],min(nums[i],minF[I-1]* nums[I]);

  }

  return *max_element(maxF.begin()、maxf . end());

  }

  };

  98.环形子阵列的最大和

  类别解决方案{

  公共:

  int maxSubarraySumCircular(vector int nums){

  /*

  根据问题的求解可以看出,环子阵的最大和有两种可能,一种是不使用环的情况,

  另一种是使用戒指的情况。

  1.如果不使用环,可以直接通过53题的思路,一步一步求整个数组的最大子序列和。

  2.使用环时,必须包含两个元素A[n-1]和A[0],并从A[1]到A[n-2]进行解释。

  该子数组必须包含负数。[否则,只能通过一次最大子序列和来获得结果]

  */

  //初始数据

  int n=nums . size();

  if(n==1)返回nums[0];

  //创建一个dp数组

  vector int DP max(n);

  向量int dpMin(n);

  //dp数组初始化

  DP max[0]=nums[0];

  DP min[0]=nums[0];

  //dp逻辑

  for(int I=1;I n;i) {

  dpMax[i]=max(dpMax[i - 1] nums[i],nums[I]);

  dpMin[i]=min(dpMin[i - 1] nums[i],nums[I]);

  }

  int max 1=* max _ element(DP max . begin()、DP max . end());

  int min 1=* min _ element(DP min . begin()、DP min . end());

  int temp=accumulate(nums.begin(),nums.end(),0);

  int max 2=temp-min 1;

  If(max2==0) {//考虑所有负数据的情况,返回数组中的最大值。

  返回max1

  }

  返回max(max1,max 2);

  }

  };

  面试问题17.24。最大子矩阵

  /*

  最大子阵的二维升级版。技术:前缀和最大子数组

  想法是这样的:

  I,j双指针遍历所有可能的两个“行对”,即子矩阵的上下两边,决定了矩阵的高度。

  将i-j之间的每一列(计算每一列的累计和)作为一维数组中的一项,找出其中最大的子数组,即匹配的子矩阵的宽度。

  */

  类别解决方案{

  公共:

  vector int getmax matrix(vector vector int matrix){

  //已知

  int rows=matrix . size();

  int cols=matrix[0]。size();

  //结果

  向量int ans(4,-1);

  int maxMat=INT _ MIN//最大值,初始化

  //遍历

  for(int up=0;上行;Up) {//遍历起始行

  向量整数(列);//对矩阵中的两行元素求和

  for(int bottom=up;底部行;Bottom) {//遍历结束线

  //最大字段和问题数

  int DP=0;//记录最大总和

  int left=0;//开始列

  for(int right=left;右列;右){//遍历列//遍历数组,其实就是边遍历边完成求和。

  nums[右]=矩阵【下】【右】;//将新的一行中第我个元素加到前面若干行在位置我的和

  if(dp 0) { //前面的字段有和为正,可以把前面一部分也带上

  DP=nums[右];

  } else { //前面一段为负,拖后腿直接抛弃

  DP=nums[右];

  左=右;

  }

  if(dp maxMat) { //与历史最大值比较,若大于,更新。不断记录较好的结果

  maxMat=dp

  ans[0]=up;

  ans[1]=左;

  ans[2]=bottom;

  ans[3]=右;

  }

  }

  }

  }

  返回美国国家标准(American National Standards的缩写)

  }

  };

  363.矩形区域不超过K的最大数值和

  类别解决方案{

  公共:

  int maxSumSubmatrix(vector vector int matrix,int k) {

  int ans=INT _ MIN

  int m=matrix.size(),n=matrix[0].size();

  for(int I=0;我是m;i) { //枚举上边界

  向量int sum(n);

  for(int j=I;j m;j) { //枚举下边界

  for(int c=0;c n;c) {

  sum[c]=矩阵[j][c];//更新每列的元素和

  }

  set int sumSet { 0 };

  int s=0;

  for (int v : sum) {

  s=v;

  auto lb=sumset。下界(s-k);

  如果(磅!=sumSet.end()) {

  ans=max(ans,s-* lb);

  }

  sumSet.insert

  }

  }

  }

  返回美国国家标准(American National Standards的缩写)

  }

  };

  单串:打家劫舍系列

  198.打家劫舍

  类别解决方案{

  公共:

  int rob(vector int nums) {

  //已知信息

  int n=nums。size();

  如果(n==1)返回nums[0];

  //创建数据处理数组

  向量int DP(n);

  DP[0]=nums[0];

  dp[1]=max(nums[0],nums[1]);

  for(int I=2;i i) {

  //偷第我间房和不偷第我间房,取最大

  dp[i]=max(dp[i - 2] nums[i],DP[I-1]);

  }

  返回DP[n-1];

  }

  };

  213.打家劫舍二

  类别解决方案{

  公共:

  int rob(vector int nums) {

  int n=nums。size();

  如果(n==1)返回nums[0];

  如果(n==2)返回max(nums[0],nums[1]);

  //偷头不偷尾,偷尾不偷头

  vector int nums1(nums.begin(),nums。begin()n-1);

  向量int nums2(nums.begin() 1,nums。end());

  return max(myRob(nums1),myRob(num S2));

  }

  int myRob(vector int nums) {

  int n=nums。size();

  //向量数组

  //vector int DP(n);

  //DP[0]=nums[0];

  //dp[1]=max(nums[0],nums[1]);

  //for(int I=2;i i) {

  //dp[i]=max(dp[i - 2] nums[i],DP[I-1]);

  //}

  //返回DP[n-1];

  //滚动数组

  int pre=nums[0],cur=max(nums[0],nums[1]);

  for(int I=2;i i) {

  内部温度=当前温度

  cur=max(pre nums[i],cur);

  pre=温度

  }

  返回坏蛋

  }

  };类别解决方案{

  私人:

  int rob(vector int nums) {

  int size=nums。size();

  vector int dp(size,0);

  DP[0]=nums[0];

  dp[1]=max(nums[0],nums[1]);

  for(int I=2;我尺寸;i ) {

  dp[i]=max(dp[i - 2] nums[i],DP[I-1]);

  }

  返回DP[size-1];

  }

  公共:

  int deleteAndEarn(vector int nums){

  int maxVal=0;

  对于(自动赋值:nums){

  maxVal=max(maxVal,val);

  }

  //构造(点数和)数组

  vector int sum(maxVal 1);

  //填充数组

  对于(自动赋值:nums){

  sum[val]=val;

  }

  //动态规划

  返回rob(总和);

  }

  };

  740.删除并获得点数

  类别解决方案{

  公共:

  int deleteAndEarn(vector int nums){

  //重点:选中nums[i],就不选数字[i - 1]和nums[n 1]

  int maxVal=0;

  对于(自动赋值:nums) {

  maxVal=max(maxVal,val);

  }

  vector int numSum(maxVal 1,0);

  对于(自动赋值:nums) {

  numSum[val]=val;

  }

  返回myRob(numSum);

  }

  int myRob(vector int nums) {

  int n=nums。size();

  如果(n==1)返回nums[0];

  vector int dp(n,0);

  DP[0]=nums[0];

  dp[1]=max(nums[0],nums[1]);

  for(int I=2;i i) {

  dp[i]=max(dp[i - 2] nums[i],DP[I-1]);

  }

  返回DP[n-1];

  }

  };

  1388.3牛顿块披萨

  类别解决方案{

  公共:

  int maxsize切片(矢量int切片){

  vector int nums1(slices.begin(),切片。begin()切片。size()-1);

  向量整数2(切片。begin() 1,切片。end());

  return max(myRob(nums1),myRob(num S2));

  }

  int myRob(vector int nums) {

  int n=nums。size();

  int choose=(n ^ 1)/3;

  向量向量int DP(n ^ 1,向量int(选择1));

  for(int I=1;i i) {

  for(int j=1;j=选择;j) {

  dp[i][j]=max(dp[i - 1][j],(i - 2=0?DP[I-2][j-1]:0)nums[I-1]);

  }

  }

  返回DP[n]选择];

  }

  };

  单串:变形,需要两个位置的情况

  873.最长的斐波那契子序列的长度

  类别解决方案{

  公共:

  int lenLongestFibSubseq(vector int arr){

  int n=arr。size();

  //f(i,j),以arr[i]为结尾,前一个是arr[j]的数列长度

  向量向量int dp(n,向量int(n));

  //需要哈希表快速遍历有无arr[k],实现arr[k] arr[j]=arr[i]

  unordered_map int,int umap

  for(int I=0;I n;i) {

  umap[arr[I]]=I;

  }

  //dp逻辑

  int ans=0;

  for(int I=1;I n;i) {

  for(int j=0;j I;j) {

  //arr[k]的值

  int temp=arr[I]-arr[j];

  //若存在

  如果(umap。count(temp)umap[temp]j){

  DP[I][j]=DP[j][umap[temp]]1;

  } else { //若不存在

  DP[I][j]=2;

  }

  ans=max(ans,DP[I][j]);

  }

  }

  还ans 2?ans:0;

  }

  };类别解决方案{

  私人:

  int搜索(向量int nums,int right,int target) {

  int left=0;

  while (left=right) {

  int mid=left((右-左)1);

  if (nums[mid]==target) {

  返回中间的

  }

  nums[mid]目标?右=中1:左=中1;

  }

  return-1;

  }

  公共:

  int lenLongestFibSubseq(vector int arr){

  向量向量int dp(arr.size()),向量int(arrsize());

  int ret=0;

  for(int I=1;我arr。size();i) {

  for(int j=0;j I;j) {

  int index=search(arr,j - 1,arr[I]-arr[j]);

  dp[i][j]=(index!=-1) ?DP[j][index]1:2;

  ret=max(ret,DP[I][j]);

  }

  }

  返回ret 2?ret:0;

  }

  };类别解决方案{

  公共:

  int lenLongestFibSubseq(vector int arr){

  int n=arr。size();

  //f(i,j),以arr[i]为结尾,前一个是arr[j]的数列长度

  向量向量int dp(n,向量int(n));

  //dp逻辑

  int ans=0;

  for(int I=1;I n;i) {

  for(int j=0;j I;j) {

  //arr[k]的值

  int temp=arr[I]-arr[j];

  //递增数组用二分

  int left=0;

  int right=j-1;

  DP[I][j]=2;//若不存在

  while(left=right) {

  int mid=left(右-左)/2;

  if(arr[mid]==temp) {

  DP[I][j]=DP[j][mid]1;//若存在

  打破;

  } else if(arr[mid] temp) {

  右=中1;

  }否则{

  左=中1;

  }

  }

  ans=max(ans,DP[I][j]);

  }

  }

  还ans 2?ans:0;

  }

  };

  1027.最长等差数列

  类别解决方案{

  公共:

  int longestArithSeqLength(vector int nums){

  int n=nums。size();

  向量向量int dp(n,向量int (n,2));

  unordered_map int,int umap

  int ans=0;

  for(int I=0;I n;i) {

  for(int j=I 1;j n;j) {

  int target=nums[I](nums[I]-nums[j]);

  if(umap.count(target)) {

  DP[I][j]=DP[umap[target]][I]1;

  }

  //否则{

  //DP[I][j]=2;

  //}

  ans=max(ans,DP[I][j]);

  }

  umap[nums[I]]=I;

  }

  返回美国国家标准(American National Standards的缩写)

  }

  };

  单串:与其他算法配合

  368.最大整除子集

  类别解决方案{

  公共:

  vector int largestdivibsetype(vector int nums){

  int n=nums。size();

  //排序

  sort(nums.begin()、nums。end());

  //dp数组,以nums[i]结尾,子集最大值

  //第一步:动态规划找出最大子集的个数、最大子集中的最大整数

  向量int dp(n,1);

  int maxSize=1;

  int maxVal=nums[0];

  //dp逻辑

  for(int I=1;I n;i) {

  for(int j=0;j I;j) {

  if(nums[i] % nums[j]==0) { //题目中说「没有重复元素」很重要

  dp[i]=max(dp[i],DP[j]1);

  }

  if(maxSize dp[i]) {

  maxSize=DP[I];

  maxVal=nums[I];

  }

  }

  }

  //倒退获得最大子集

  矢量判断是否需要交叉

  if (maxSize==1) {

  //ans。push _ back(nums[0]);

  //返回美国国家标准(American National Standards的缩写)

  返回{ nums[0]};

  }

  for(int I=n-1;i=0 maxSize 0- i) {

  if(DP[I]==maxSize maxVal % nums[I]==0){

  ans。push _ back(nums[I]);

  maxVal=nums[I];

  maxSize-;

  }

  }

  返回美国国家标准(American National Standards的缩写)

  }

  };写在后面

  加油

  乐观是一首激昂优美的进行曲,时刻鼓舞着你向事业的大路勇猛前进!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • c语言调用退出函数 c语言退出整个程序怎么写
  • c语言中怎么给函数初始化 c语言的初始化语句
  • c语言编写函数计算平均值 c语言求平均函数
  • 详解c语言中的字符串数组是什么,详解c语言中的字符串数组结构,详解C语言中的字符串数组
  • 表达式求值c++实现,c语言实现表达式求值
  • 看懂c语言基本语法,C语言详解,C语言的基本语法详解
  • 用c语言实现快速排序算法,排序算法设计与实现快速排序C语言,C语言实现快速排序算法实例
  • 深入解析c语言中函数指针的定义与使用方法,深入解析c语言中函数指针的定义与使用情况,深入解析C语言中函数指针的定义与使用
  • 描述E-R图,E-R图举例,关于C语言中E-R图的详解
  • 折半查找法C语言,折半查找算法(算法设计题)
  • 折半查找法C语言,c语言折半法查找数据,C语言实现折半查找法(二分法)
  • 扫雷小游戏c++代码设计,c语言扫雷游戏源代码,C语言实现扫雷小游戏详细代码
  • 怎样统计程序代码行数,C语言统计行数,C#程序员统计自己的代码行数
  • 基于c语言的贪吃蛇游戏程序设计,用c语言编写贪吃蛇游戏程序,C语言实现简单的贪吃蛇游戏
  • 图的两种遍历算法,图的遍历算法代码c语言,Python算法之图的遍历
  • 留言与评论(共有 条评论)
       
    验证码: