每周一道算法题009:找二进制对称的日期

题目:

把年月日表示为YYYYMMDD这样的8位整数,然后把这个整数转换成二进制数并且逆序排列,再把得到的二进制数转换成十进制数,求与原日期一致的日期。求得的日期要在上一次东京奥运会(1964年10月10日)到下一次东京奥运会(预定举办日期为2020年7月24日)之间。

思路:

从起始时间开始逐天累加,对每一天进行进制转换并反转,然后比较,如果相同就输出,不同就继续,直至到达结束时间。

解答:

php:

function findDate($begin, $end)
{
    $beginDate = new DateTime($begin);
    $endDate = new DateTime($end);
    while ($beginDate != $endDate) {
        $dateNum = $beginDate->format("Ymd");
        $binStr = decbin($dateNum);
        $revStr = strrev($binStr);
        if ($revStr == $binStr) {
            echo $dateNum . "\n";
        }
        $beginDate = $beginDate->add(new DateInterval(‘P1D‘));
    }
}

findDate("1964-10-10", "2020-07-24");

输出:

19660713
19660905
19770217
19950617
20020505
20130201

golang:

package main

import (
    "fmt"
    "strconv"
    "time"
)

func main() {
    t1 := time.Date(1964, 10, 10, 0, 0, 0, 0, time.Local)
    t2 := time.Date(2020, 7, 24, 0, 0, 0, 0, time.Local)
    findDate(t1, t2)
}

func findDate(begin, end time.Time) {
    for begin != end {
        // 将日期格式化为字符串
        dateNum := begin.Format("20060102")

        // 字符串转为数字
        dateInt, _ := strconv.Atoi(dateNum)

        // 转为二进制
        dateBin := strconv.FormatInt(int64(dateInt), 2)
        revBin := Reverse(dateBin) // 反转二进制字符串
        if revBin == dateBin {
            fmt.Println(dateNum)
        }

        // 日期累加
        dd, _ := time.ParseDuration("24h")
        begin = begin.Add(dd)
    }
}

// 反转字符串
func Reverse(s string) string {
    runes := []rune(s)
    for from, to := 0, len(runes)-1; from < to; from, to = from+1, to-1 {
        runes[from], runes[to] = runes[to], runes[from]
    }
    return string(runes)
}

输出:

19660713
19660905
19770217
19950617
20020505
20130201

原文地址:https://blog.51cto.com/ustb80/2430663

时间: 2024-07-31 22:38:30

每周一道算法题009:找二进制对称的日期的相关文章

算法——一天一道算法题篇——找只出现一次的两个数

找只出现一次的两个数 题目: 一个整型数组里除了两个数字只出现一次之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 举例说明: 现在有一个数组:{1,3,4,2,4,3}; 假设数组元素的规模不是很大,想要找到只出现一次的元素,可以定义一个辅助数组,flag[100];里面存放的是数组元素出现的次数,flag数组的下标表示的是数组:{1,3,4,2,4,3}里的元素. 代码如下: package hello.ant; public class AlogArrayFind2 {

认真对待每一道算法题 之 找明星问题 - 淘宇瀚

n个人中只有一个明星,明星不认识其他所有的人,而其他人都认识明星,不是明星的人可能认识也可能不认识.你每次只可以问一个人是否认识另一个人这样的问题,问最少问多少次可以找出明星. 做法1: 将所有人站队,按照顺序(假如编号分别为1.2.3..n),首先问1,2互相认识,有四种情况出现: (1)1 认识 2,2不认识1, 认识别人的肯定不是明星,排除1: (2)1 不认识2,2认识1, 根据(1)的道理,同样可以排除2: (3)1与2 互相认识,可以断定,两个人都不是明星,随机删除一个就好: (4)

每周一道算法题003:翻牌

问题: 有100张写着数字1-100的牌,并按顺序排列.最开始所有牌都是背面朝上放置.某人从第2张牌开始,隔1张牌翻牌.然后第2, 4, 6, -,100张牌就会变成正面朝上.接下来,另一个人从第3张牌开始,隔2张牌翻牌(原本背面朝上的,翻转成正面朝上:原本正面朝上的,翻转成背面朝上).再接下来,又有一个人从第4张牌开始,隔3张牌翻牌.像这样,从第n张牌开始,每隔n-1张牌翻牌,直到没有可翻动的牌为止.求当所有牌不再变动时,所有背面朝上的牌的数字. 思路: 这道题思路有很多种: 思路1设i为轮次

每周一道算法题005:切木棒

问题: 假设要把长度为n厘米的木棒切分为1厘米长的小段,但是1根木棒只能由1人切分,当木棒被切分为3段后,可以同时由3个人分别切分木棒.求最多有m个人时,最少要切分几次. 譬如n=8,m=3时如下图所示,切分4次就可以了. 求当n=20,m=3时的最少切分次数.求当n=100,m=5时的最少切分次数. 思路: 这道题最难的不是算法,而是理解题意.木棒刚开始只有1根,题目规定"1根木棒只能由1人切分",此时由1人切分后,变成2根:2根木棒再做切分,也要满足"1根木棒只能由1人切

每周一道算法题001:回文数

题目: 找出大于10的最小的2进制,8进制,10进制都是回文数的最小的数.回文数指的是正读和反读都是一样的数,例如:33,10001,123454321... 思路: 先转换进制,然后统一处理成字符串进行比较 解答: PHP function execute(){ $x = 11; while (1) { if ($x == strrev($x) && decbin($x) == strrev(decbin($x)) && decoct($x) == strrev(deco

每周一道算法题011:最长公共子串

问题: 求以下几组单词的最长公共子串的长度1.fish和fosh2.fish和hish3.fish和vista 思路: 可以用表格法,横纵坐标分别是两个单词,如果字符相同,就用左上角的数字加1,最后取表格中的最大值. 解答: php: <?php // 找出两个单词的最长公共子串 function findLongestSubString($word1, $word2) { $len1 = strlen($word1); $len2 = strlen($word2); $cell = array

每周一道算法题002:四则运算

问题: 求位于1000-9999,满足如下条件的数: 各位数字间加入四则运算符,也可省略,使得按四则运算计算的结果为原数字的各位数逆序排列. 例如:351 → 3×51 = 153 思路: 遍历1000-9999所有的数字,切分并组合运算符,拼成四则运算的算式然后计算.4位数中最大的数是9999,他可以被拆成999+9=1008,逆排后不可能等于原数,减法和除法不可能计算出比原数更大的数,所以只需要考虑乘法. php提供了eval函数,可以很方便的计算,但是需要对数字进行处理,因为08开头的数字

每周一道算法题006:抽签组合

问题: 有如下3支队伍,每个队伍都有2名队员.team1:A,B;team2:C,D;team3:E,F; 现在每个队出1个人,组成一个队去探险,请列出所有的组队方式. 思路: 这就是一个组合的问题,每个队里挑一人,那么总共应该有222=8种组合方式.如果暴力求解,那就是三层循环嵌套.但如果问题扩展一下,变成10个队,每个队10人,就无法暴力求解了,至少代码是没有扩展性的. 有如下一种思路: 循环所有的队伍第一次取出A,B两名队员,存起来:第二次取出C,D两名队员,与前一轮存下的队员进行交叉组合

每周一道算法题:兑换零钱

问题: 已知可兑换的零钱种类有1元,5元,10元,20元4种,现在有100块钱要换成零钱且总数量少于15张,有几种换法?分别是什么? 思路: 已知有[1,5,10,20]这样的一个可选数据集S,现在要从中取出n个数,每个数的张数为a,使得a1xn1+a2xn2+...aixni = 100. 最大的面额是20,总共需要100/20=5张,这是最少的张数,所以循环的下限是5,上限题目已经限定了,是15. 也就是说,从S这个数据集中,取5-15个数,使得他们的和为100,数是可以重复的. 先考虑最简