Google面试题俄罗斯套娃问题

1,136 阅读1分钟

俄罗斯套娃问题的描述:

给定一些标记了宽度和高度的信封,宽度和高度以整数对形式(w, h)出现。当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。请计算最多能有多少个信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。

说明:不允许旋转信封

思路

建立一个矩阵,一行是长一行是宽

先按长进行排序,遇到长度相等的信封按宽继续排序

对比两次大小,大者即为结果

算法本质是LIS算法的一种变种,算是一种比较高效的方法总比穷举法好

代码


envelop <- read_csv(
  "length,width
  5,4
  6,4
  6,7
  2,3
  3,1
  6,6
  6,2"
)

LIS.num <- function(data_tibble){
  return_c <- c()
  res <- 1
  for(i in 1:nrow(data_tibble)){
    if(length(return_c) == 0||
       (as.numeric(data_tibble[i,1]) > return_c[(res - 1) * 2 - 1] 
        && as.numeric(data_tibble[i,2]) > return_c[(res - 1) * 2])){
      return_c[res * 2 -1] <- as.numeric(data_tibble[i,1])
      return_c[res * 2] <- as.numeric(data_tibble[i,2])
      res <- res + 1
    }else if(as.numeric(data_tibble[i,1]) > return_c[(res - 1) * 2 - 1] 
             && as.numeric(data_tibble[i,2]) < return_c[(res - 1) * 2]){
      change_index <- which(return_c[seq(2,res * 2,by = 2)] > as.numeric(data_tibble[i,2]))[1]
      return_c[change_index] <- as.numeric(data_tibble[i,2])
      return_c[change_index - 1] <- as.numeric(data_tibble[i,1])
    }
  }
  return(length(return_c) %/% 2)
}

(envelop <- envelop[order(envelop$length,envelop$width),])
cat("该测试用例的叠加个数最大是",LIS.num(envelop))

以上代码就是R语言实现俄罗斯套娃问题的解题,借助LIS的动态规划思想,加以改造即可