如果一个数组A[1…n]中超过半数的元素都相同时,该数组被称为含有一个主元素。给定一个数组,设计一个有效算法,确定该数组中是否含有一个主元素。如果有,找出这个元素。该数组的元素之间不一定存在顺序,如整

题目三:

2.23如果一个数组A[1…n]中超过半数的元素都相同时,该数组被称为含有一个主元素。给定一个数组,设计一个有效算法,确定该数组中是否含有一个主元素。如果有,找出这个元素。该数组的元素之间不一定存在顺序,如整数之间就存在顺序,可以作形如"A[i]>A[j]吗"的比较与此不同的是,该数组中的元素则不一定能做出这样的比较。(比如可以把数组中的元素设想成
GIF文件)但是,却可以在常量时间内回答如下列形式的问题“A[i]>A[j]吗”
(1)给出一个算法,以0(nlogn)时间完成本题

算法思想:

根据主元素的定义与题目要求,由于不能比较A[i]与A[j]大小,所以就不可以用排序的方式进行寻找主元素,但是仍然可以比较元素之间相等与不相等,这里我采用删除数组中两个不相等的元素,主元素不变的思想,寻找主元素。

更新:

5年前刚上大学的时候写的代码,现在看了一下,确实存在bug,但是基本思想是对的,嗯,思想就是这么简单。也是凑巧刚好看到了邮件提醒,已经不怎么写博客了,既然看到了就顺手改了。在原来基础上增加个判断就行了,时间复杂度仍然是O(N)。简单的改了一下原来的代码,没有编译运行过(嫌麻烦。。。),直接在leetcode上跑了下,最后加了个leetcode AC的代码。

代码:

#include<iostream>
#include <vector>
#define INFINITY 100000
using namespace std;
int GetMain(vector<int>&A)
{
	int count = 0, mainE;
    for (int i = 0; i < A.size(); i++) {
        if (count == 0) {
            mainE = A[i];
            count = 1;
        } else {
            if (mainE == A[i])
                count++;
            else
                count--;
        }
    }
   // 再次遍历以确认 mainE 是否确实是多数元素
    count = 0;
    for (int i = 0; i < A.size(); i++) {
        if (A[i] == mainE)
            count++;
    }
    if (count > A.size() / 2)
        return mainE;
    else
        return INFINITY;
}
int main(void)
{
	vector<int>A;
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		int temp;
		cin >> temp;
		A.push_back(temp);
	}
	int temp = GetMain(A);
	if (temp != INFINITY)
		cout << "主元素为:" << temp;
	else
		cout << "没有主元素";
	system("pause");
	return 0;
}

测试案例:

在这里插入图片描述

力扣AC代码:

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int count = 0, mainE;
        for (int i = 0; i < nums.size(); i++) {
            if (count == 0) {
                mainE = nums[i];
                count = 1;
            } else {
                if (mainE == nums[i])
                    count++;
                else
                    count--;
            }
        }
        // 再次遍历以确认 mainE 是否确实是多数元素
        count = 0;
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] == mainE)
                count++;
        }
        if (count > nums.size() / 2)
            return mainE;
        else
            return -1;
    }
};
### 回答1: 好的,这个问题是一个编程问题。可以使用双指针法,一个指针 i 指向当前珂是遍历到的位置,另一个指针 j 指向当前应该被替换的位置。遍历数组,如果当前值不等于 val,则将其赋值给 nums[j],同将 j 加一。遍历结束后,j 就是新数组的长度。代码实现如下: ``` int removeElement(vector<int>& nums, int val) { int i = 0, j = 0; while (i < nums.size()) { if (nums[i] != val) { nums[j] = nums[i]; j++; } i++; } return j; } ``` ### 回答2: 我们可以使用双指针的方法来解决这个问题。 首先,我们初始化两个指针,一个指向数组的起始位置,另一个指向数组的末尾位置。 然后,我们对数组进行遍历,如果当前元素等于给定的值val,我们将末尾指针指向的元素复制到当前位置,并将末尾指针向前移动一位。这样,我们就相当于将数组中所有等于val的元素都移到了数组的末尾。 遍历结束后,末尾指针的位置就指向了数组中最后一个非val元素的位置。我们返回末尾指针的位置加一,即为新数组的长度。 以下是具体的实现代码: def removeElement(nums, val): start = 0 end = len(nums) - 1 while start <= end: if nums[start] == val: nums[start] = nums[end] end -= 1 else: start += 1 return start 该算法间复杂度为O(n),其中n为数组的长度。因为我们需要遍历一次数组来移除元素。 同,该算法满足题目要求的空间复杂度为O(1),因为我们没有使用额外的数组空间,只是利用两个指针来进行原地修改输入数组。 ### 回答3: 题目要求原地修改输入数组,移除所有值等于给定值的元素,并返回移除后数组的新长度。 我们可以使用双指针的方法来解决这个问题。定义两个指针,一个指向当前要比较的元素,另一个指向要放置下一个不等于给定值的元素的位置。 具体步骤如下: 1. 初始化两个指针,一个指向数组的开头(i=0),另一个指向数组的末尾(end=nums.length-1)。 2. 开始遍历数组,当i<=end: a. 如果当前元素等于给定值,则将end处的元素复制到当前位置,然后将end指针向前移动一位。这样可以将数组末尾的值移动到当前位置,并且保证end指针指向的元素一定等于给定值。 b. 如果当前元素不等于给定值,则将i指针向后移动一位,继续比较下一个元素。 3. 当遍历结束,返回i的值作为新数组的长度。 代码实现如下: ``` public int removeElement(int[] nums, int val) { int i = 0; int end = nums.length - 1; while (i <= end) { if (nums[i] == val) { nums[i] = nums[end]; end--; } else { i++; } } return i; } ``` 间复杂度分析:该算法只需一次遍历数组,因此间复杂度为O(n),其中n为数组的长度。 空间复杂度分析:该算法只使用了常数个额外变量,因此空间复杂度为O(1)。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

K_K_Chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值