《剑指Offer》--数学

文章介绍了两种算法问题的解决方案:一是找出数组中出现次数超过一半的数字,使用了投票算法;二是解决约瑟夫问题,即在环形排列中按特定规则淘汰人,最后剩下的人的编号。同时,还提供了一个计算从1到n整数中1出现次数的方法。
摘要由CSDN通过智能技术生成

《剑指Offer》–算法

#include<iostream>
#include<vector>
using namespace std;


/*Q:数组中出现次数超过一半的数字?
R:res的票+1,非众数-1,根据题目的描述则一定有所有数字的票数和 > 0 ;
若数组的前 a 个数字的票数和 == 0 ,则数组剩余 (n-a) 个数字的票数和一定仍 > 0 ,
即后 (n-a)个数字的最多数仍为 res。(严格来说是超过一半的数)*/
int MoreThanHalfNum_Solution(vector<int> nums)
{
	int majority = nums[0];
	for (int i = 1, cnt = 1; i < nums.size(); i++) {
		cnt = nums[i] == majority ? cnt + 1 : cnt - 1;
		cout << "cnt" <<cnt<< endl;
		if (cnt == 0) {
			majority = nums[i];
			cnt = 1;
		}
	}

	int cnt = 0;
	for (auto val : nums) {
		if (val == majority)
			cnt++;
		
	}
    return cnt > (nums.size() / 2) ? majority : 0;

}

/*约瑟夫问题:圆圈中最后剩下的数?
有n个人围成一圈,从第一个人开始报数,
报到m的人出圈,剩下的人继续从1开始报数,
直到剩下一个人。问最后剩下的人的编号是多少?
还有 个比较简单的递归表达式 f(N,M)=(f(N−1,M)+M)%N
 */
 int LastRemaining_Solution(int n, int m) {
	 
	 cout << "************LastRemaining_Solution************" << endl;
	 int count = 0;
	 int i = 0;
	 int k = -1;	
	  int* a = new int[n];
	 for ( i = 0; i <n; i++)  //矩阵赋值为0;
		  a[i]=0;


	 while (count <n-1)
	 {
		  i = 0;
			 while (i < m)
			 {
				 k = (k + 1) % n;
				 if (a[k] == 0)
				 {
					 i++;
					 if (i % m == 0)
					 {
						 a[k] = -1;
						 count++;
					 }
				 }

			 }	
	 }

	 for (i = 0; i < n; i++)
		 cout << a[i];
	 

	 for (i = 0; i < n; i++) {
		 if (a[i] == 0) {
			 k= i + 1;
			 break;
		 }
	 }
     delete a;
	 return k;

}

void test_MoreThanHalfNum_Solution()
{
	vector<int> nums = { 1,1,1,4,4,4,5,5,5,5,5,5,5,5,5,5};
	int majority = MoreThanHalfNum_Solution(nums);
	cout << "数组出现最多的个数是:" << majority << endl;
}


// 从1到n整数中1出现的次数
int  NumberOf1Between1AndN_Solution(int n) {
	int cnt = 0;
	for (int m = 1; m <= n; m *= 10) {
		int a = n / m, b = n % m;
		cnt += (a + 8) / 10 * m + (a % 10 == 1 ? b + 1 : 0);
	}
	return cnt;
}

int main()
{
	
	cout << "test" << endl;
	int i= NumberOf1Between1AndN_Solution(13);
	cout <<i<< endl;

	getchar();
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值