清明假期刷题,爬山 4/56

在这里插入图片描述
如上图

1 无重复字符子串,主要思想是 map 记录每个字符出现的长度,一定要要求是1次。出现一个记录一个
双指针滑动窗,如果第一次出现就加上,然后于 result 比较长度,长的就覆盖 result。当遇到相同元素的时候
就进入循环 begin 前移,在移动中,把原来的元素一一在 map 里--,直到当前元素在 map 中出现次数为1

string getLongestSubstr(string ss) {
	string result = "";
	int begin = 0;
	int right = 0;
	string word = "";
	int char_map[128] = {0};

	for (int i=0;i<ss.size(),i++) {
		char_map[ss[i]] ++;
		if(char_map[ss[i]] == 1) {
			word += ss[i];
			if (word.size() > result.size()) {
				result = word;
			}
		} else {
			while(begin<i && char_map[ss[i]] > 1) {
				char_map[char_map[begin]]--;
				begin++;
			}
			word.assign(ss, begin,i-begin+1);
		}
	}
	return result;
}

2 数据流中的中位数,使用大顶堆于小顶堆
float getMidNum(std::vector<int> &vec) {
	priority_queue<int, std::vector<int>, greater<int>> small_heap;
	priority_queue<int, std::vector<int>, less<int>> big_heap;

	for(ahto i:vec) {
		if(big_heap.empty()) {
			big_heap.push(i);
		} else {
			if (big_heap.size() == small_heap.size()) {
				if(small_heap.top() < i) {
					small_heap.push(i);
				} else{
					big_heap.push(i);
				}
			} else if(big_heap.size() +1 == small_heap.size()) {
				if (i < small_heap.top()) {
					big_heap.push(i);
				} else {
					big_heap.push(small_heap.top());
					small_heap.pop();
					small_heap.push(i);
				}
			} else if (big_heap.size() == small_heap() +1) {
				if(i > big_heap.top()) {
					small_heap.push(i);
				} else {
					small_heap.push(big_heap.top());
					big_heap.pop();
					big_heap.push(i);
				}
			}
		}
	}
	if (big_heap.size() == small_heap.size()) {
		return (big_heap.top() + small_heap.top())>>1;
	} else if (big_heap.size() > small_heap.size()) {
		return big_heap.top();
	} else {
		return small_heap.top();
	}
}


3 剪绳子 II, 求剪短的绳子剪成 k段的时候长度乘积最大,至少减为两段,主要是拆解为2,3的因子,主要是3因子居多即最大,类似于爬楼梯
  int getMultiLen(int n) {
  	std::vector<int> res(1001,0);
  	res[1] = 1;
  	res[2] = 1;//(1*1)
  	res[3] = 2;//(1*2)
  	res[4] = 4;//(2*2)
  	res[5] = 6;//(2*3)
  	res[6] = 9;//(3*3)
  	//从因子7开始
  	for (int i = 7; i <= n; i++)	
  	{
  		res[i] = res[i-3]*3;
  	}
  	return res[n];
  }

4 构建乘积数组,求除去自己的数组其他元素乘积合
std::vector<int> getMultiArr(std::vector<int> &vec) {
	int size = vec.size();
	std::vector<int> res(size+1,0);

	int left = 1;
	int right = 1;
	for (int i = 0; i < size; i++)
	{
		res[i] *= left;
		left *= vec[i];

		res[size-1-i] *= right;
		right *= vec[size-1-i];
	}
	return res;

}
5 数组中出现次数超过一半的数字	,可以用 map,可以用临时变量

int getNum(std::vector<int> &nums){
	//用 map
	std::map<int, int> mp;
	for(auto num:nums) {
		mp[num]++;
		if (mp[num] > nums.size()>>1) {
			return num;
		}
	}
	//用零时变量
	int cur = 1;
	int res = nums[0];
	for (int i = 1; i < nums.size(); i++) {
		if (nums[i] == res) {
			cur++;
		} else {
			cur--;
		}
		if (cur == 0) {
			cur = 1;
			res = nums[i];
		}
	}
	return res;
}

6 数组中数字出现的次数	,数组中有两个数字出现一次,其他出现两次
std::vector<int> getTwoNum(std::vector<int> &nums) {
	int s = 0;
	for(auto num : nums) {
		s ^= num;
	}
	//利用 S,-S 与操作得到最后一个1的位置,两个出现一次的数字这个位置肯定不相同,否则S 就是0了
	//然后利用这个位置分别与nums中元素判断将其分割成两队(1,1,3),(2,2,6);
	int k = s&(-s);
	std::vector<int> res;
	for (auto num:nums) {
		if (k&num) {
			res[0] ^= num;
		} else {
			res[1] ^= num;
		}
	}
	return res;
}

7 二叉树的最近公共祖先	
TreeNode* getFather(TreeNode* root, TreeNode* p, TreeNode* q) {
	if(!root || root == p|| root == q) {
		return root;
	}

	TreeNode* left = getFather(root->left, p, q);
	TreeNode* right = getFather(root->right, p, q);

	//如果左右都有,返回根
	if (left && right) {
		return root;
	}
	return left? left:right;
}
8 二叉搜索树的后序遍历序列	,找到最后一个根节点,然后从左边遍历第一个大于它的就是右子树起点,遍历右子树,有比他小的就 false,然后递归
bool isValidPostOrder(std::vector<int> nums) {
	if (nums.empty()) {
		return true;
	}
	return checkOrder(nums, 0, nums.size() -1);
}

bool checkOrder(std::vector<int> &nums, int start, int end) {
	if (start > end) {
		return true;
	}
	int root = nums[end];
	int i=start;
	for (; i < end; i++) {
		if (nums[i] > root) {
			//找到了右子树起点
			break;
		}
	}
	for (int j=i;j<end;j++) {
		if (nums[j] < root) {
			return false;
		}
	}
	//没有的话分别遍历左右子树
	
	bool left = checkOrder(nums, start, i - 1);
	bool right = checkOrder(nums, i, end - 1);
	return left&&right;
}


9 原地删除排序数组中的重复项,大神解法
 int deleteSame(std::vector<int> &nums) {
	int j=0;
	for (int i = 1; i < nums.size(); i++) {
		if (nums[j] != nums[i]) {
			nums[++j] = nums[i];
		}
	}
	return ++j;//nums.assign(0,++j);
}	
10 第 k 个数(丑数)有些数的素因子只有 357,请设计一个算法找出第 k 个数。
注意,不是必须有这些素因子,而是必须不包含其他的素因子。例如,前几个数按顺序应该是 135791521int getKNum(int k) {
	int i3 = 0;
	int i5 = 0;
	int i7 = 0;
	std::vector<int> nums(1001,1); 
	for (int i = 1; i < k; i++) {
		nums[i] = min(nums[i3]*3, min(nums[i5]*5, nums[i7]*7));
		if (nums[i] == nums[i3]*3) i3++;
		if (nums[i] == nums[i5]*5) i5++;
		if (nums[i] == nums[i7]*7) i7++;
	}
	return nums[k-1];
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值