华为机试再回忆--第一题

之前写的第一题有误,上个厕所过来赶紧给删了,怕误导大家。题目如下:

题目:输出整数序列中重复的数字

描述:编写一个程序,用户输入任意长度(小于等于10)的整数序列,整数值都大于0,程序输出序列中所有重复的数组并且数组的顺序和输入保持一致

输入:数字序列,一行数字,长度小于1000;两个数字之间用逗号隔开,所有数字均为整数且大于0.

输出:重复的数字,两个数字之间以空格分隔,数字的顺序和输入一致

样例输入:3,2,2,3,4,5,6

样例输出:3,2

 

解题步骤:

1.申请一个InputArray和HelpArray,大小均为1000,初始化为0

2.将输入字符串存入InputArray并计算实际大小

3.双重循环遍历输入数组,如果有相同的元素则再判断HelpArray数组里面是否存在这个元素

4.若HelpArray没有则存入,否则继续遍历

5.最后顺序HelpArray中的非零元素,即可

 

复制代码
  1 #include <iostream>
  2 #include <string>
  3 using namespace std;
  4 
  5 #define MaxSize 1000
  6 
  7 int main()
  8 {
  9     int *InputArray=new int[MaxSize];
 10     int *HelpArray=new int[MaxSize];
 11     for(int i=0;i<MaxSize;i++)
 12     {
 13         InputArray[i]=0;
 14         HelpArray[i]=0;
 15     }
 16     
 17     
 18     string s;
 19     cin>>s;
 20 
 21 
 22     int count=0;
 23     int sum=0;
 24     i=0;
 25     int temp;
 26     while(true)
 27     {
 28         if(s[i+1]!=','&&(i+1)!=s.length())
 29         {
 30             sum=sum*10+(s[i]-'0')*10;
 31         }
 32         else
 33         {
 34             sum=sum+(s[i]-'0');
 35             temp=sum;
 36             InputArray[count++]=sum;
 37             if(i==s.length()-1)
 38             {
 39                 break;
 40             }
 41             
 42             sum=0;
 43             i=i+2;
 44             continue;
 45         }
 46         i++;
 47         
 48     }
 49 
 50 
 51   int RealLen=count;
 52 
 53   for(i=0;i<count;i++)
 54   {
 55       if(InputArray[i]<=0)
 56       {
 57         return 0;
 58       }
 59   }
 60       
 61 
 62    int countnew=0;
 63     for(i=0;i<RealLen;i++)
 64     {
 65         for(int j=0;j<RealLen;j++)
 66         {
 67             if(i!=j)
 68             {
 69                 bool flag=true;
 70                 if(InputArray[i]==InputArray[j])
 71                 {
 72                     for(int k=0;k<MaxSize;k++)
 73                     {
 74                         if(InputArray[i]==HelpArray[k])
 75                         {
 76                             flag=false;
 77                         }
 78                     }
 79                     
 80                     
 81                     if(flag)
 82                     {
 83                         HelpArray[countnew++]=InputArray[i];
 84                     }
 85                 }
 86             }
 87         }
 88     }
 89     
 90     for(i=0;i<MaxSize;i++)
 91     {
 92         if(HelpArray[i]==0)
 93         {
 94             break;
 95         }
 96         else
 97         {
 98             cout<<HelpArray[i]<<" ";
 99         }
100     }
101     
102     cout<<endl;
103     delete[] InputArray;
104     InputArray=NULL;
105     
106     delete[] HelpArray;
107     HelpArray=NULL;
108     return 0;
109 }
复制代码

运行截图:


<think>好的,用户现在想了解牛客网华为的第40。首先,我需要回忆一下华为的常见型和结构。华为通常包含编程,涉及数据结构、算法、字符串处理、动态规划等。牛客网上的目可能有一定的难度,尤其是后面的目,比如第40,可能属于较难的部分。 用户之前询问过C++的编译时多态,可能对编程有一定基础,现在转向具体算法的求解。我需要先确定第40的具体内容,但可能用户没有提供目细节,所以需要推测或查找相关信息。不过,由于无法直接访问外部资源,我需要依靠已有的知识库或者常见的华为型进行推测。 常见的华为可能包括字符串操作、图算法、树结构、动态规划等。比如,第40可能是类似“合唱队形”、“购物单”、“迷宫问”这样的目。假设用户无法提供具体目内容,我需要给出一个通用的解思路,或者举一个典型的例子来说明如何应对这类问。 另外,用户可能希望得到详细的解步骤,包括问分析、解思路、代码实现和注意事项。因此,我需要结构清晰地分步骤讲解,确保用户能够理解并应用到实际问中。 考虑到用户可能需要具体的例子,假设第40是一个典型的动态规划问,比如“最长递增子序列”或其变种,或者是字符串处理问。比如,可能的目是计算字符串的最长回文子串,或者是图的最短路径问。 在不确定具体目内容的情况下,我可以选择一个常见的华为作为例子,例如“合唱队形”问,这通常涉及动态规划,且是华为中的经典目。这个问的描述是:N位同学站成一排,要求其中的某些同学出列,使得剩下的同学排成合唱队形,即先递增再递减。求最少需要几位同学出列。 接下来,我需要详细分析这个问,给出解思路、动态规划的应用,以及代码实现的示例。同时,需要注意边界条件和优化点,帮助用户理解如何应对类似的问。 在回答过程中,需要使用中文,结构清晰,分步骤讲解,并确保代码的正确性和可读性。同时,要提醒用户注意测用例的覆盖和可能的陷阱,比如重复元素、极端情况等。 总结来说,我需要: 1. 假设一个可能的华为第40,例如“合唱队形”问。 2. 分步骤解析问,包括问描述、输入输出、解思路。 3. 使用动态规划的方法详细讲解如何求解最长递增子序列及其变种。 4. 提供代码示例,并解释关键部分。 5. 总结注意事项和优化建议。 这样可以帮助用户即使面对不同的具体目,也能掌握解的方法和思路,提升解决类似问的能力。</think>--- ### **牛客网华为第40详解** 由于华为库会定期更新,且目编号可能因版本不同有所变化,以下内容基于典型的**华为高频型**进行分析。假设第40涉及**动态规划**或**字符串处理**,我们以一道经典目**“合唱队形问”**为例进行详细解析,其解思路与代码实现具有广泛适用性。 --- #### **一、目描述** **问**: N位同学站成一排,音乐老师要请其中的$(N-K)$位同学出列,使得剩下的$K$位同学排成**合唱队形**。合唱队形要求: - 队形为**先严格递增再严格递减** - 不允许仅递增或仅递减 求最少需要多少同学出列,即求最大的$K$值。 **输入示例**: ``` 8 186 186 150 200 160 130 197 200 ``` **输出示例**: ``` 4 ``` **解释**: 最终队列为 `150 160 130` 或 `160 130 197` 等,需要移除4人。 --- #### **二、解思路** **核心思想**: 1. **双向动态规划** - 对每个位置,计算其**左侧最长递增子序列长度**(LIS) - 计算其**右侧最长递减子序列长度**(LDS) - 两者相加再减1(当前元素被重复计算一次),即为以该元素为中心的合唱队形最大长度 2. **状态转移方程** - 递增序列:$dp\_inc[i] = \max(dp\_inc[j] + 1) \quad (0 \leq j < i \text{且} arr[j] < arr[i])$ - 递减序列:$dp\_dec[i] = \max(dp\_dec[j] + 1) \quad (i < j < n \text{且} arr[j] < arr[i])$ **步骤分解**: 1. 计算每个位置的左侧最长递增子序列 2. 计算每个位置的右侧最长递减子序列 3. 遍历所有位置,找到最大$(dp\_inc[i] + dp\_dec[i] - 1)$ 4. 最终结果为$n - \max\_len$ --- #### **三、代码实现** ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { int n; cin >> n; vector<int> heights(n); for (int i = 0; i < n; ++i) { cin >> heights[i]; } vector<int> dp_inc(n, 1); // 左侧递增序列长度 for (int i = 1; i < n; ++i) { for (int j = 0; j < i; ++j) { if (heights[j] < heights[i]) { dp_inc[i] = max(dp_inc[i], dp_inc[j] + 1); } } } vector<int> dp_dec(n, 1); // 右侧递减序列长度 for (int i = n-2; i >= 0; --i) { for (int j = n-1; j > i; --j) { if (heights[j] < heights[i]) { dp_dec[i] = max(dp_dec[i], dp_dec[j] + 1); } } } int max_len = 0; for (int i = 0; i < n; ++i) { max_len = max(max_len, dp_inc[i] + dp_dec[i] - 1); } cout << n - max_len << endl; return 0; } ``` --- #### **四、关键点解析** 1. **时间复杂度**: - 双重循环导致时间复杂度为$O(n^2)$ - 可通过贪心+二分优化至$O(n \log n)$(适用于大规模数据) 2. **边界条件**: - 所有身高相同时,输出$n-1$(只能保留1人) - 严格递增或严格递减时,需保证至少有一个峰顶 3. **华为常见陷阱**: - 输入数据可能存在多个相同值,需注意严格递增/递减的判断 -用例可能包含极端情况(如n=0或n=1) --- #### **五、优化思路(高阶)** 1. **贪心+二分优化** 将LIS/LDS的计算优化为$O(n \log n)$: ```cpp // 以递增序列为例 vector<int> tails; for (auto num : heights) { auto it = lower_bound(tails.begin(), tails.end(), num); if (it == tails.end()) { tails.push_back(num); } else { *it = num; } dp_inc[i] = tails.size(); } ``` 2. **空间压缩** 使用滚动数组减少空间占用 --- #### **六、相似型拓展** 1. **最长递增子序列**(LeetCode 300) 2. **山脉数组**(LeetCode 845) 3. **俄罗斯套娃信封问**(LeetCode 354) --- **总结**:华为中类似目考察动态规划的核心应用能力,解关键在于将问分解为已知模型(如LIS)。掌握双向DP的思路后,可灵活应用于多种变种型。实际考中需注意代码鲁棒性和边界条件处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值