遇到的好玩的算法及实现

这篇文章列举了一系列算法问题,包括将数组中的零移动到末尾、计算能盛最多水的容器面积、爬楼梯的动态规划解法以及如何反转整数。此外,还涉及逻辑推理问题,如分糖和识别绿色标签的人数,以及编程实现匹配袜子的问题,分别用Java、Python、C和Dart语言展示了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算法就像脑筋急转弯,平时在技术交流群中看到大家提出的算法小问题,总想动动脑尝试一下,看看如果是自己会怎么解决,总是欲罢不能,现在把之前见到的别人提出的问题,也有很多之前很多做了没有记录的,现在把记得的做一个记录,后面再有遇到会持续更新。

1、移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

2、盛最多水的容器

给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

3、爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

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语言实现

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值