小於n的最大數

liang302發表於2024-09-22

貪心+回溯:
找某位的最小值的時候用set實現的二分

求hack

#include <algorithm>
#include <unordered_set>
#include <vector>
#include <iostream>
using namespace std;
// getMaxDigitLtD 獲取小於指定數字的最大數字。
int getMaxDigitLtD(const vector<int> &digits, int digit) {
  for (auto it = digits.rbegin(); it != digits.rend(); it++) {
    if (*it < digit) {
      return *it;
    }
  }
  return -1;
}

// getMaxNumLtN 獲取小於 n 的最大數。
int getMaxNumLtN(vector<int> &digits, int n) {
  // 獲取 n 的每一位數字。12345
  vector<int> ndigits;
  while (n > 0) {
    ndigits.push_back(n % 10);
    n /= 10;
  }
  // 排序給定的數字陣列。 5 4 3 2 1 
  sort(digits.begin(), digits.end());
  // 數字寫入 map 用於快速檢視是否存在。
  unordered_set<int> set;
  for (auto v : digits) {
    set.insert(v);
  }

  // 目標數的每一位數字。
  vector<int> tdigits(ndigits.size());

  // 從原數字高位到低位遍歷,儘可能地取相同值,除了最後一位,最後一位需要比他小。
  for (int i = ndigits.size() - 1; i >= 0; i--) {
    // 存在相同的數字,可以直接看下一位(最後一位除外)。
    if (i > 0 && set.find(ndigits[i]) != set.end()) {
      tdigits[i] = ndigits[i];
      continue;
    }
    
    // 找不到相同的數字,那就找到存在小於當前位的最大數字。
	// 如果最高位真的找到比他小的而且不是0的,說明之後數字都可以取nums最大 ,break 
    // 123 直接放99 
	// 213 直接放09 
    auto d = getMaxDigitLtD(digits, ndigits[i]);
    if (d != -1) {
      tdigits[i] = d;
      break;
    }
    
	// 需要回溯。陣列{2} target:219 2xy
	// 現在x=2就已經無敵了  
    for (i++; i < ndigits.size(); i++) {
      tdigits[i] = 0;
      // 小於當前位的最大數字。
      d = getMaxDigitLtD(digits, ndigits[i]);
      if (d > 0) {
        tdigits[i] = d;
        break;
      }
      // 最高位也沒有小於其的最大數字。
      if (i == ndigits.size() - 1) {
        tdigits.resize(tdigits.size() - 1);
      }
    }
    break;
  }

  // 拼裝目標數。
  int target = 0;
  for (int i = tdigits.size() - 1; i >= 0; i--) {
    target *= 10;
    if (tdigits[i] > 0) {  
      target += tdigits[i];
      continue;
    }
    // 取數字陣列中最大的數字。
    target += digits.back();
  }
  return target;
}

int main() {
	
	
  auto digits = vector<int>{5, 9};
  cout << getMaxNumLtN(digits, 5555) << endl;
  
  
  digits = vector<int>{0, 2, 9, 4};
  cout << getMaxNumLtN(digits, 2533) << endl;

  digits = vector<int>{1, 2, 5, 4};
  cout << getMaxNumLtN(digits, 2543) << endl;

  digits = vector<int>{1, 2, 5, 4};
  cout << getMaxNumLtN(digits, 2541) << endl;

  digits = vector<int>{1, 2, 9, 4};
  cout << getMaxNumLtN(digits, 2111) << endl;

	  
}

相關文章