算法就像脑筋急转弯,平时在技术交流群中看到大家提出的算法小问题,总想动动脑尝试一下,看看如果是自己会怎么解决,总是欲罢不能,现在把之前见到的别人提出的问题,也有很多之前很多做了没有记录的,现在把记得的做一个记录,后面再有遇到会持续更新。
1、移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
void moveZeroes(int* nums, int numsSize){
int j = 0;
for (int i = 0; i < numsSize; ++i) {
if (nums[i] != 0) {
nums[j] = nums[i];
if (i != j) {
nums[i] = 0;
}
j++;
}
}
}
2、盛最多水的容器
给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
int maxArea(int* height, int heightSize){
int max = 0;
int i = 0, j = heightSize - 1;
while (i < j) {
if (height[i] < height[j]) {
max = max > height[i] * (j - i) ? max : height[i] * (j - i);
i++;
} else {
max = max > height[j] * (j - i) ? max : height[j] * (j - i);
j--;
}
}
return max;
}
3、爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
int climbStairs(int n){
int a1 = 0;
int a2 = 1;
int a3 = 0;
for (int i = 1; i <= n; ++i) {
a3 = a1 + a2;
a1 = a2;
a2 = a3;
}
return a3;
}
4、给定一个整数,反向输出,例如123 -> 321,不能使用字符串
4.1 先把数字从后往前取出每一位数字,放到一个数组中,然后遍历数组,根据数组索引位置,确定新的数字位置,例如[3, 2, 1],则3对应的就是300,就为 3乘以10的2次方,2对应的就是20,就是2乘以10的一次方,依次类推,结果累加。
- (NSInteger)reverseNsInteger:(NSInteger)input
{
NSMutableArray *mutArr = [NSMutableArray array];
NSInteger temp = input;
while (temp) {
NSInteger a = temp % 10;
[mutArr addObject:@(a)];
temp = temp / 10;
}
NSInteger result = 0;
for (int i = 0; i < mutArr.count; ++i) {
NSInteger value = [mutArr[i] integerValue];
result = result + value * pow(10, mutArr.count - i - 1);
}
return result;
}
4.2 直接把原数字对10进行求余,累加到结果上,因为每次累加是在最后一位,前面的数字会左移,也就是增大了10倍,所以每次对原结果进行乘10,然后加上上次剩余数字对10求余的结果。
- (NSInteger)reverseNsInteger2:(NSInteger)input
{
NSInteger result = input % 10;
NSInteger temp = input / 10;
while (temp) {
result = result * 10 + temp % 10;
temp = temp / 10;
}
return result;
}
5、有一个6克和21克的砝码,怎样称量三次将420克的糖分成270克和150克
5.1 > 因为总重量是偶数,所以应该总重量和6克砝码均分
420 + 6 = 426 / 2 = 213
5.2 > 会分出213克和207克
213 + 207 = 420
5.3 > 现在都是奇数,所以应该和21克的砝码合起来均分
207 + 21 = 228 / 2 = 114
5.4 > 207克会被分成114克和93克两份
114 + 93 = 207
5.5 > 114克直接用天平均分
114 / 2 = 57
5.6 > 最后213 + 57 = 270,剩下的就是150克
6、一桌子人,每个人额头贴一个标签红色和绿色,绿色至少一个,大家能看到别人的标签,看不到自己的,然后开始闭眼,觉得自己是绿色标签的拍一下手掌,第一闭眼没人拍,第二次和第三次也没有拍,第四次有一个人拍了,请问绿色标签有几个,答4个
6.1 > 第一次没人拍,说明至少有两个,如果只有一个,那一个人看到比人就知道自己了就会拍,所以至少两个,L1和L2都认为自己不是
6.2 > 第二次没人拍,说明至少3个,如果仅仅是两个,L1或L2看到对方后,就会知道自己是,所以会拍,没拍就是他们看到的至少2个,所以至少还有L3
6.3 > 第三次没人拍说明至少有4个,第二次没拍,L3看到两个,就会明白自己是,应该会拍,但是没拍,说明大家看到的至少是3个
6.4 > 第四次有一个人拍了,L4看到3个,三次都没拍,明白自己就是,所以拍了
补充:不完美,是最后4个人全拍了,因为绿色的四个人看到的都是3个,所以第四次应该都知道了,如果,绿签人数多于4,第四次应该也不拍,应该大家看到的是大于4的,所以还没意识到自己是绿签,所以最后描述有问题,应该第四次有人拍掌,但不应该说有一个人拍掌
7、找袜子,尝试用了不同语言代码实现了一下
7.1 > 题目描述
有一大堆袜子必须按颜色配对。给定一个表示每只袜子颜色的整数数组,确定有多少双具有匹配颜色的袜子。
7.2 > 输入格式
第一行是一个整数n,表示袜子的数量
第二行是n个用空格分隔的整数,表示对应袜子的颜色
7.3 > 输出格式
多少双袜子匹配成功
7.4 > ##### 样例 #####
样例输入:
7
1 2 1 2 1 3 2
样例输出:
2
7.5 > Java代码实现
package com.siwh.java;
import java.util.Date;
public class HelloWord {
private static int testCount;
public static void main(String[] args) {
System.out.println("Hello word!");
int[] dataList = new int[]{1, 2, 1, 2, 1, 3, 2, 3, 1};
showTest(dataList);
}
public static void showTest(int[] tlist) {
Date date = new Date();
System.out.println(date.getTime());
int totalCount = tlist.length;
for (int i = 0; i < totalCount; i++) {
int a = tlist[i];
for (int j = i + 1; j < totalCount; j++) {
if (tlist[i] == tlist[j]) {
testCount++;
int temp = tlist[i + 1];
tlist[i+1] = tlist[j];
tlist[j] = temp;
i++;
break;
}
}
}
Date date1 = new Date();
System.out.println(date1.getTime());
System.out.println(testCount);
}
}
7.6 > Python实现
# -*- coding: utf-8 -*-
import random
import time
import random
count = 0
dataList = [] #[1, 2, 1, 2, 1, 3, 2, 3, 4, 7, 8, 5, 7, 4]
# 1. 完全匹配不上
# for i in range(1000):
# dataList.append(i)
# 2. 每个都最快匹配
# for i in range(500):
# dataList.append(i)
# dataList.append(i)
# 3. 随机数据
for i in range(1000):
dataList.append(random.randint(0,999))
print(len(dataList))
totalCount = len(dataList);
can = False
print(time.time())
for i in range(totalCount):
if can:
can = False
else:
a1 = dataList[i]
for j in range(i+1, totalCount):
if (a1 == dataList[j]):
can = True
count += 1;
temp = dataList[i+1];
dataList[i+1] = dataList[j]
dataList[j] = temp
break
print(count)
print(time.time())
7.7 > C语言实现
void caculateData(int numsSize, int* nums) {
printf("开始时间 ==== %lld \n", get_timestamp());
int count = 0;
for (int i = 0; i < numsSize; i++) {
for(int j = i + 1; j < numsSize; j++) {
if (nums[i] == nums[j]) {
count += 1;
int temp = nums[i + 1];
nums[i+1] = nums[j];
nums[j] = temp;
i += 1;
break;
}
}
}
printf("结束时间 ==== %lld \n", get_timestamp());
printf("执行结果 %d \n", count);
}
7.8 > Dart语言实现
void showCount(List<int> dataList) {
print('开始时间 === ${DateTime.now().millisecondsSinceEpoch}');
int count = 0;
for (int i = 0; i < dataList.length; i++) {
for (int j = i + 1; j < dataList.length; j++) {
if (dataList[i] == dataList[j]) {
count += 1;
int temp = dataList[i + 1];
dataList[i + 1] = dataList[j];
dataList[j] = temp;
i += 1;
break;
}
}
}
print('结束时间 === ${DateTime.now().millisecondsSinceEpoch}');
print("匹配成功 ====== $count");
}
/// 1000个数据测试
int totalCount = 1000;
for (int i = 0; i < totalCount; i++) {
testData.add(i);
}
print("测试1 ===============");
showCount(testData);
testData = [];
for (int i = 0; i < totalCount / 2; i++) {
testData.add(i);
testData.add(i);
}
print("测试2 ===============");
showCount(testData);
testData = [];
for (int i = 0; i < totalCount; i++) {
final _random = new Random();
testData.add(_random.nextInt(1000));
}
print("测试3 ===============");
showCount(testData);
/// 测试结果,毫秒
flutter: 测试1 ===============
flutter: 开始时间 === 1666938053452
flutter: 结束时间 === 1666938053456
flutter: 匹配成功 ====== 0
flutter: 测试2 ===============
flutter: 开始时间 === 1666938053456
flutter: 结束时间 === 1666938053456
flutter: 匹配成功 ====== 500
flutter: 测试3 ===============
flutter: 开始时间 === 1666938053461
flutter: 结束时间 === 1666938053462
flutter: 匹配成功 ====== 269