美文网首页
请听第二道算法题:修改矩阵

请听第二道算法题:修改矩阵

作者: 夏天的风_495e | 来源:发表于2019-07-21 16:43 被阅读0次

今天来看一下美团2019春招的第二道算法题。

image

首先还是分析一下题目的规律。

根据题意,每个格子e的上下左右四个相邻元素必须相等,且不等于e。

我们定义一个概念:当格子的横纵坐标之和为奇数时我们称该格子为奇数格子,当格子的横纵坐标之和为偶数时我们称该格子为偶数格子。

我们可以发现,对于满足题意的矩阵,所有偶数格子上的数均相等,所有奇数格子上的数均相等,且奇数格子上的数不等于偶数格子上的数。

若要求总的修改的数字数量最少,等价于转换为保留出现次数最多的数字,我们可以分解为奇数格子上保留出现次数最多的数字,同时偶数格子上也保留出现次数最多的数字。

当然还必须保证奇数格子上保留的数字不能等于偶数格子上保留的数字。

我们约定将ni出现的次数ci记为(ni, ci)的形式。

我们考虑最一般的情况,即奇数格子上至少有两种不同的数字,偶数格子上也是至少有两种不同的数字。

我们把奇数格子上的数按出现次数从大到小排序,得到(n1,c1),(n2,c2)。。。

我们把偶数格子上的数按出现次数从大到小排序,得到(m1,d1),(m2,d2)。。。

如果n1 != m1,那么保留n1和m1一定就是最优解;如果n1==m1,就有两种方案可以选择,一是保留n1和m2,二是保留n2和m1,总之,最优解一定在保留n1和m1、保留n1和m2或保留n2和m1中产生。

但是在写代码时这样去判断的话会增加复杂性,在代码中可以直接两重循环,判断在保留n1和m1、n1和m2、n2和m1、n2和m2时,保留的数字数量,取最大值即可。两重循环时多考虑了保留n2和m2这种情况,多考虑一种情况不影响最终的结果。

上golang代码:

package main

import (
  "bufio"
  "fmt"
  "os"
  "sort"
  "strconv"
  "strings"
)

type pair struct {
  num int
  cnt int
}

type PairList []pair

func (p PairList) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
func (p PairList) Len() int           { return len(p) }
func (p PairList) Less(i, j int) bool { return p[i].cnt > p[j].cnt }

func main() {
  nr := bufio.NewReader(os.Stdin)
  nm, _ := nr.ReadString('\n')
  nm = strings.Trim(nm, "\r\n")
  n, _ := strconv.Atoi(strings.Split(nm, " ")[0])
  m, _ := strconv.Atoi(strings.Split(nm, " ")[1])
  odde := make(map[int]int) //统计奇数格子上各数字出现的次数
  evene := make(map[int]int)//统计偶数格子上各数字出现的次数
  for i := 0; i < n; i++ {
    str, _ := nr.ReadString('\n')
    str = strings.Trim(str, "\r\n")
    line := strings.Split(str, " ")

    for j := 0; j < m; j++ {
      e, _ := strconv.Atoi(line[j])
      if (i+j)%2 == 0 {
        cnt, ok := odde[e]
        if !ok {
          odde[e] = 1
        } else {
          odde[e] = cnt + 1
        }
      } else {
        cnt, ok := evene[e]
        if !ok {
          evene[e] = 1
        } else {
          evene[e] = cnt + 1
        }
      }
    }
  }
  oddlist := make(PairList, 0, len(odde))
  for n, c := range odde {
    oddlist = append(oddlist, pair{n, c}) // 将map中的kv对封装成pair结构体,用于排序
  }
  sort.Sort(oddlist)
  if len(oddlist) == 1 {
      oddlist = append(oddlist, pair{-1, 0})
  }

  evenlist := make(PairList, 0, len(evene))
  for n, c := range evene {
    evenlist = append(evenlist, pair{n, c})
  }
  sort.Sort(evenlist)
  if len(evenlist) == 1 {
      evenlist = append(evenlist, pair{-1, 0})
  }

  var retained int // 保留的数字数量,取最大
  for i := 0; i < 2; i++ {
    for j := 0; j < 2; j++ {
      if oddlist[i].num != evenlist[j].num {
        retained = max(retained, oddlist[i].cnt + evenlist[j].cnt)
      }
    }
  }

  fmt.Println(n*m - retained)
}

func max(a, b int) int {
  if a > b {
    return a
  } else {
    return b
  }
}

实现代码的时候有一个细节需要注意:

因为前面在分析的时候,假设了n2和m2均存在,但是实际上n2或m2可能不存在,即奇数格子或偶数格子上只有一种数字。

所以在代码中的60行和69行,需要判断list长度是否为1,如果是,则填充一个pair{num:-1, cnt:0}。

可以验证,这种处理方式是能够保证准确结果的,并且提交代码也ac了:)

欢迎关注博主个人微信公众号~~~

image

相关文章

  • 请听第二道算法题:修改矩阵

    今天来看一下美团2019春招的第二道算法题。 首先还是分析一下题目的规律。 根据题意,每个格子e的上下左右四个相邻...

  • 2021-07-28 华为

    第一道题:贪心算法第二道题:拓扑排序第三道题:路径和 III 原因:memo.copy()是浅拷贝,特别对于这种路...

  • 顺时针输出数字矩阵

    Q: 之前朋友跟我聊了道算法题,是顺时针输出数组矩阵,如图1所示: 简单写了下算法,语言无所谓,思路都差不多,我用...

  • 教你几招算法笔试的套路

    相关推荐: 一文秒杀四道原地修改数组的算法题[https://labuladong.gitbook.io/algo...

  • 【算法】打印算法题总结

    前言 本文记录了我对打印算法题的总结。先说说什么事打印算法题,就是按照一定的规则打印二维矩阵。例如:旋转正方形矩阵...

  • 每日两道算法题 - 矩阵旋转

    问题 给定一个 n × n 的二维矩阵,按顺时针旋转 90 度在原矩阵上进行旋转。 思路 依次对矩阵最外层进行90...

  • 矩阵系列算法题

    1.转圈打印矩阵 【题目】给定一个整型矩阵matrix,请按照转圈的方式打印它。例如:1 2 3 45 6 7 8...

  • Codeforces 1365A - Matrix Game

    日常一道算法题。 翻译 Ashish 和 Vivek 在一个 n 行 m 列的矩阵上玩一个游戏,轮流认领格子。未被...

  • [2]十道算法题【Java实现】

    前言 清明不小心就拖了两天没更了~~ 这是十道算法题的第二篇了~上一篇回顾:十道简单算法题 最近在回顾以前使用C写...

  • 表达式去括号

    date: 2018-9-15昨天做了道算法题,感觉有点局限性,今天重新修改了下。 数据格式 类型:string,...

网友评论

      本文标题:请听第二道算法题:修改矩阵

      本文链接:https://www.haomeiwen.com/subject/ctcvlctx.html