数组题目一

设数组R【】中的n个元素中有多个0元素,设计一个算法,将R中所有的非0元素一次移动到R数组的前端

 

void move(int R[],int n)
{
 int i=0,j=n-1;
 while(i<=j)
 {
  if(R[i]>0)
   i++;
  else if(R[i]==0)
  {
   int t=R[i];
   R[i]=R[j];
   R[j--]=t;
  }
 }
}


void main()
{
 int M[6]={2,4,0,5,7,0};
 cout<<"重新排之前:"<<endl;
 for(int i=0;i<6;i++)
  cout<<M[i]<<" ";
 cout<<endl;
 move(M,6);
 cout<<"重新排之后"<<endl;
 for(i=0;i<6;i++)
  cout<<M[i]<<" ";
 cout<<endl;
}

这里要注意的是,本来我的move函数中没有N的,当时忽略了一点,就是数组在传参的时候,就化为了指针,所以我的j一开始的时候就等于0,所以这样子根本就达不到重新排的效果!这一点需要注意

<think>好的,用户想了解C++中的标记数组题目。首先,我需要确定用户的基础,可能是个刚开始学习算法的人,或者正在准备编程面试。标记数组通常用于处理需要记录状态的问题,比如查找重复元素、统计出现次数等。 接下来,我应该解释什么是标记数组。用简单的例子说明,比如一个布尔数组,用来标记某个元素是否出现过。然后,举几个常见的应用场景,比如判断数组是否有重复元素、统计素数、矩阵中的特定路径问题等。 需要确保例子具体且易于理解。例如,判断重复元素时,可以用一个数组来记录每个数字是否被访问过。统计素数可以用埃拉托斯特尼筛法,这也是标记数组的应用。矩阵中的问题,比如岛屿数量,可以用二维标记数组记录访问过的位置。 还要注意代码的正确性,比如在C++中数组的大小可能需要根据问题调整,或者使用更灵活的结构如vector。同时提醒用户注意可能的越界问题,或者空间复杂度的问题,如果数据范围很大,可能需要优化,比如使用位运算代替数组。 用户可能想知道如何选择使用标记数组,或者在不同问题中的变体。比如有时可以用原地算法,用输入数组本身作为标记,节省空间。这时候需要给出例子,比如将访问过的位置为特定值,如-10。 还要考虑常见错误,比如忘记初始化标记数组,或者在回溯时没有正确恢复状态,导致结果错误。这时候需要强调初始化和状态管理的重要性。 最后,总结标记数组的优缺点,适用场景,以及可能的替代方法,比如哈希表在某些情况下可以替代标记数组,但可能有不同的时间空间复杂度。 现在需要把这些思路组织成结构清晰的回答,分步骤说明,并给出代码示例,确保语法正确,用中文解释清楚。</think>在C++算法题目中,标记数组种通过辅助空间记录状态信息的常用技巧。以下是分步骤详解: 、核心概念 标记数组本质是一个辅助数组,通常用bool或int类型实现,用于记录原数组元素的状态。典型应用场景包括: 1. 元素是否被访问过 2. 元素是否满足特定条件 3. 动态规划中的状态标记 二、典型应用场景及代码示例 1. 查找重复元素(LeetCode 217) 问题:判断数组中是否存在重复元素 解法:用标记数组记录元素出现次数 $$nums = [1,2,3,1]$$ ```cpp bool containsDuplicate(vector<int>& nums) { // 假数据范围在0-10^4之间 bool flag[10001] = {false}; for(int num : nums) { if(flag[num]) return true; flag[num] = true; } return false; } ``` 2. 素数筛选(埃拉托斯特尼筛法) 问题:找出小于n的所有素数 ```cpp vector<int> countPrimes(int n) { vector<bool> isPrime(n, true); for(int i=2; i*i<n; ++i) { if(isPrime[i]) { for(int j=i*i; j<n; j+=i) isPrime[j] = false; } } vector<int> res; for(int i=2; i<n; ++i) if(isPrime[i]) res.push_back(i); return res; } ``` 3. 矩阵路径问题(LeetCode 79) 问题:在二维字符矩阵中查找单词 ```cpp bool exist(vector<vector<char>>& board, string word) { vector<vector<bool>> visited(board.size(), vector<bool>(board[0].size(), false)); for(int i=0; i<board.size(); ++i) for(int j=0; j<board[0].size(); ++j) if(dfs(board, visited, i, j, word, 0)) return true; return false; } bool dfs(...) { if(...) return true; visited[i][j] = true; // 标记当前位置已访问 // 四个方向递归搜索 visited[i][j] = false; // 回溯时恢复状态 return false; } ``` 三、优化技巧 1. 原地标记:当允许修改输入数组时,可直接修改原数组 ```cpp // 将访问过的元素标记为'#' board[i][j] = '#'; // 回溯时恢复原值 board[i][j] = original; ``` 2. 位运算压缩:当数据范围较大时,可用bitset优化空间 ```cpp bitset<1000000> flag; // 仅需125KB内存 ``` 四、注意事项 1. 初始化问题:务必正确初始化标记数组 2. 下标映射:当元素值可能为负数时,需进行偏移处理 3. 空间复杂度:数据量极大时需考虑内存限制 五、常见变种题型 1. 寻找消失的数字(LeetCode 448) 2. 矩阵中的最长递增路径(LeetCode 329) 3. 解数独问题(LeetCode 37) 掌握标记数组技巧能有效解决约30%的数组/矩阵类算法题,建议通过LeetCode对应tag的题目进行专项训练。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值