【LeetCode】17. 電話號碼的字母組合

文章目錄

  • 17. 電話號碼的字母組合
    • 題目描述
    • 示例 1:
    • 示例 2:
    • 示例 3:
    • 提示:
    • 解題思路
      • 算法分析
      • 問題本質分析
      • 回溯法詳解
      • 組合生成過程可視化
      • 數字映射關系
      • 各種解法對比
      • 算法流程圖
      • 邊界情況處理
      • 時間復雜度分析
      • 空間復雜度分析
      • 關鍵優化點
      • 實際應用場景
      • 測試用例設計
      • 代碼實現要點
    • 完整題解代碼

17. 電話號碼的字母組合

題目描述

給定一個僅包含數字 2-9 的字符串,返回所有它能表示的字母組合。答案可以按 任意順序 返回。

給出數字到字母的映射如下(與電話按鍵相同)。注意 1 不對應任何字母。

在這里插入圖片描述

示例 1:

輸入:digits = “23”
輸出:[“ad”,“ae”,“af”,“bd”,“be”,“bf”,“cd”,“ce”,“cf”]

示例 2:

輸入:digits = “”
輸出:[]

示例 3:

輸入:digits = “2”
輸出:[“a”,“b”,“c”]

提示:

  • 0 <= digits.length <= 4
  • digits[i] 是范圍 [‘2’, ‘9’] 的一個數字。

解題思路

這道題要求根據電話號碼的數字組合,生成所有可能的字母組合。這是一個經典的回溯算法問題,需要枚舉所有可能的組合。每個數字對應3-4個字母,需要生成所有可能的排列組合。

算法分析

這道題的核心思想是回溯枚舉,主要解法包括:

  1. 回溯法:使用遞歸和回溯生成所有組合(推薦)
  2. 迭代法:使用隊列進行層序遍歷
  3. 優化版本:使用strings.Builder提高字符串操作效率
  4. BFS方法:廣度優先搜索生成組合
  5. 遞歸分治:使用分治思想逐步構建組合

問題本質分析

graph TDA[電話號碼字母組合] --> B[數字映射]B --> C[組合生成]C --> D[回溯枚舉]B --> E[2→abc, 3→def, 4→ghi]B --> F[5→jkl, 6→mno, 7→pqrs]B --> G[8→tuv, 9→wxyz]C --> H[每個位置選擇字母]C --> I[生成所有可能組合]D --> J[遞歸回溯]E --> K[映射關系建立]F --> KG --> KH --> L[組合策略]I --> LJ --> L

回溯法詳解

flowchart TDA[輸入digits字符串] --> B{digits為空?}B -->|是| C[返回空數組]B -->|否| D[初始化結果數組]D --> E[調用回溯函數backtrack]E --> F[backtrack(index=0, current="")]F --> G{index == len(digits)?}G -->|是| H[添加current到結果]G -->|否| I[獲取當前數字對應的字母]H --> J[返回結果]I --> K[遍歷每個字母]K --> L[選擇當前字母]L --> M[遞歸調用backtrack(index+1)]M --> N[回溯:移除當前字母]N --> O{還有字母?}O -->|是| KO -->|否| P[返回上一層]G --> Q[終止條件處理]Q --> R[結果收集]

組合生成過程可視化

輸入: digits = '23'
數字映射: 2→abc, 3→def
第1層: 選擇2的字母
選擇'a' → current='a'
選擇'b' → current='b'
選擇'c' → current='c'
第2層: 選擇3的字母
第2層: 選擇3的字母
第2層: 選擇3的字母
選擇'd' → 'ad'
選擇'e' → 'ae'
選擇'f' → 'af'
選擇'd' → 'bd'
選擇'e' → 'be'
選擇'f' → 'bf'
選擇'd' → 'cd'
選擇'e' → 'ce'
選擇'f' → 'cf'
最終結果: [ad,ae,af,bd,be,bf,cd,ce,cf]

數字映射關系

graph TDA[數字映射表] --> B[2 → abc]A --> C[3 → def]A --> D[4 → ghi]A --> E[5 → jkl]A --> F[6 → mno]A --> G[7 → pqrs]A --> H[8 → tuv]A --> I[9 → wxyz]B --> J[3個字母]C --> JD --> JE --> JF --> JG --> K[4個字母]H --> JI --> KJ --> L[標準按鍵]K --> M[擴展按鍵]L --> N[組合數量計算]M --> N

各種解法對比

解法對比
回溯法
迭代法
優化版本
BFS方法
遞歸分治
時間O_4^n空間O_n
時間O_4^n空間O_4^n
時間O_4^n空間O_n
時間O_4^n空間O_4^n
時間O_4^n空間O_n
推薦解法
隊列實現
性能最優
層序遍歷
分治思想
平衡性能和可讀性

算法流程圖

flowchart TDA[開始] --> B{digits為空?}B -->|是| C[返回空數組]B -->|否| D[初始化結果數組]D --> E[調用backtrack(0, '')]E --> F{index >= len(digits)?}F -->|是| G[添加current到結果]F -->|否| H[獲取當前數字的字母]G --> I[返回結果]H --> J[遍歷每個字母]J --> K[選擇當前字母]K --> L[遞歸backtrack(index+1)]L --> M[回溯:移除字母]M --> N{還有字母?}N -->|是| JN -->|否| O[返回]F --> P[遞歸終止條件]P --> Q[結果收集和返回]

邊界情況處理

邊界情況
空字符串
單個數字
多個數字
包含7或9
返回空數組
返回對應字母數組
正常回溯處理
處理4個字母的情況
特殊情況處理

時間復雜度分析

時間復雜度分析
組合數量計算
每個數字的字母數
總體復雜度
3^n 或 4^n
大部分數字3個字母
7和9有4個字母
O_4^n
最壞情況
平均情況
指數級增長

空間復雜度分析

空間復雜度分析
遞歸調用棧
結果存儲
總體空間復雜度
O_n
O_4^n
O_4^n
遞歸深度
結果數組大小

關鍵優化點

優化策略
字符串操作優化
數據結構選擇
內存管理
使用strings.Builder
數組替代map
避免不必要的內存分配
減少字符串拼接開銷

實際應用場景

應用場景
電話鍵盤
密碼生成
組合枚舉
游戲設計
手機撥號界面
密碼破解工具
排列組合計算
文字游戲
核心算法組件

測試用例設計

測試用例
基礎功能
邊界情況
特殊情況
正常數字組合
多個數字
不同長度
空字符串
單個數字
最大長度
包含7或9
重復數字
連續數字
驗證正確性
驗證特殊規則

代碼實現要點

  1. 回溯策略

    • 使用遞歸函數進行深度優先搜索
    • 在每個位置嘗試所有可能的字母
    • 到達葉子節點時收集結果
  2. 狀態管理

    • 維護當前構建的字符串
    • 記錄當前處理的位置
    • 正確進行回溯操作
  3. 映射關系

    • 建立數字到字母的映射表
    • 處理7和9的4個字母情況
    • 使用數組或map存儲映射
  4. 邊界處理

    • 空字符串返回空數組
    • 單個數字直接返回對應字母
    • 確保所有情況都有正確輸出
  5. 性能優化

    • 使用strings.Builder減少字符串拼接開銷
    • 避免不必要的內存分配
    • 選擇合適的遞歸深度

這個問題的關鍵在于理解回溯算法的核心思想掌握遞歸狀態管理,通過深度優先搜索枚舉所有可能的字母組合。特別是回溯操作,需要在每次遞歸調用后正確恢復狀態,確保能夠嘗試所有可能的組合。時間復雜度為O(4^n),其中n是digits的長度,因為每個數字最多對應4個字母。

完整題解代碼

package mainimport ("fmt""strings"
)// letterCombinations 電話號碼的字母組合 - 回溯法
// 時間復雜度: O(4^n),其中n是digits的長度,每個數字最多對應4個字母
// 空間復雜度: O(n),遞歸調用棧深度
func letterCombinations(digits string) []string {if len(digits) == 0 {return []string{}}// 數字到字母的映射digitMap := map[byte]string{'2': "abc",'3': "def",'4': "ghi",'5': "jkl",'6': "mno",'7': "pqrs",'8': "tuv",'9': "wxyz",}var result []stringvar backtrack func(index int, current string)backtrack = func(index int, current string) {// 如果已經處理完所有數字,添加當前組合到結果if index == len(digits) {result = append(result, current)return}// 獲取當前數字對應的字母letters := digitMap[digits[index]]// 嘗試每個字母for _, letter := range letters {backtrack(index+1, current+string(letter))}}backtrack(0, "")return result
}// letterCombinationsIterative 迭代法 - 使用隊列
// 時間復雜度: O(4^n)
// 空間復雜度: O(4^n),存儲所有可能的組合
func letterCombinationsIterative(digits string) []string {if len(digits) == 0 {return []string{}}// 數字到字母的映射digitMap := map[byte]string{'2': "abc",'3': "def",'4': "ghi",'5': "jkl",'6': "mno",'7': "pqrs",'8': "tuv",'9': "wxyz",}// 使用隊列存儲當前所有可能的組合queue := []string{""}// 逐個處理每個數字for i := 0; i < len(digits); i++ {letters := digitMap[digits[i]]levelSize := len(queue)// 處理當前層的所有組合for j := 0; j < levelSize; j++ {current := queue[0]queue = queue[1:]// 為當前組合添加每個可能的字母for _, letter := range letters {queue = append(queue, current+string(letter))}}}return queue
}// letterCombinationsOptimized 優化版本 - 使用strings.Builder
// 時間復雜度: O(4^n)
// 空間復雜度: O(n)
func letterCombinationsOptimized(digits string) []string {if len(digits) == 0 {return []string{}}// 使用數組映射,避免map查找開銷digitMap := [][]byte{{}, {}, // 0, 1 不對應字母{'a', 'b', 'c'},      // 2{'d', 'e', 'f'},      // 3{'g', 'h', 'i'},      // 4{'j', 'k', 'l'},      // 5{'m', 'n', 'o'},      // 6{'p', 'q', 'r', 's'}, // 7{'t', 'u', 'v'},      // 8{'w', 'x', 'y', 'z'}, // 9}var result []stringvar backtrack func(index int, current *strings.Builder)backtrack = func(index int, current *strings.Builder) {if index == len(digits) {result = append(result, current.String())return}digit := digits[index] - '0'letters := digitMap[digit]for _, letter := range letters {current.WriteByte(letter)backtrack(index+1, current)// 回溯:移除最后添加的字符currentStr := current.String()current.Reset()current.WriteString(currentStr[:len(currentStr)-1])}}backtrack(0, &strings.Builder{})return result
}// letterCombinationsBFS BFS方法 - 層序遍歷
// 時間復雜度: O(4^n)
// 空間復雜度: O(4^n)
func letterCombinationsBFS(digits string) []string {if len(digits) == 0 {return []string{}}digitMap := map[byte]string{'2': "abc",'3': "def",'4': "ghi",'5': "jkl",'6': "mno",'7': "pqrs",'8': "tuv",'9': "wxyz",}// BFS隊列queue := []string{""}for i := 0; i < len(digits); i++ {letters := digitMap[digits[i]]levelSize := len(queue)// 處理當前層的所有組合for j := 0; j < levelSize; j++ {current := queue[0]queue = queue[1:]// 為當前組合添加每個可能的字母for _, letter := range letters {queue = append(queue, current+string(letter))}}}return queue
}// letterCombinationsRecursive 純遞歸方法 - 分治思想
// 時間復雜度: O(4^n)
// 空間復雜度: O(n)
func letterCombinationsRecursive(digits string) []string {if len(digits) == 0 {return []string{}}if len(digits) == 1 {return getLetters(digits[0])}// 分治:處理第一個數字,遞歸處理剩余數字firstLetters := getLetters(digits[0])remainingCombinations := letterCombinationsRecursive(digits[1:])var result []stringfor _, letter := range firstLetters {for _, combination := range remainingCombinations {result = append(result, string(letter)+combination)}}return result
}// getLetters 獲取單個數字對應的字母
func getLetters(digit byte) []string {switch digit {case '2':return []string{"a", "b", "c"}case '3':return []string{"d", "e", "f"}case '4':return []string{"g", "h", "i"}case '5':return []string{"j", "k", "l"}case '6':return []string{"m", "n", "o"}case '7':return []string{"p", "q", "r", "s"}case '8':return []string{"t", "u", "v"}case '9':return []string{"w", "x", "y", "z"}default:return []string{}}
}func main() {// 測試用例1digits1 := "23"result1 := letterCombinations(digits1)fmt.Printf("示例1: digits = \"%s\"\n", digits1)fmt.Printf("輸出: %v\n", result1)fmt.Printf("期望: [ad ae af bd be bf cd ce cf]\n")fmt.Printf("結果正確: %t\n", len(result1) == 9)fmt.Println()// 測試用例2digits2 := ""result2 := letterCombinations(digits2)fmt.Printf("示例2: digits = \"%s\"\n", digits2)fmt.Printf("輸出: %v\n", result2)fmt.Printf("期望: []\n")fmt.Printf("結果正確: %t\n", len(result2) == 0)fmt.Println()// 測試用例3digits3 := "2"result3 := letterCombinations(digits3)fmt.Printf("示例3: digits = \"%s\"\n", digits3)fmt.Printf("輸出: %v\n", result3)fmt.Printf("期望: [a b c]\n")fmt.Printf("結果正確: %t\n", len(result3) == 3)fmt.Println()// 額外測試用例digits4 := "234"result4 := letterCombinations(digits4)fmt.Printf("額外測試: digits = \"%s\"\n", digits4)fmt.Printf("輸出數量: %d\n", len(result4))fmt.Printf("期望數量: 27 (3×3×3)\n")fmt.Printf("結果正確: %t\n", len(result4) == 27)fmt.Println()// 測試迭代版本fmt.Println("=== 迭代版本測試 ===")result1Iter := letterCombinationsIterative(digits1)result2Iter := letterCombinationsIterative(digits2)fmt.Printf("迭代版本示例1: %v\n", result1Iter)fmt.Printf("迭代版本示例2: %v\n", result2Iter)fmt.Printf("結果一致: %t\n", len(result1Iter) == len(result1) && len(result2Iter) == len(result2))fmt.Println()// 測試優化版本fmt.Println("=== 優化版本測試 ===")result1Opt := letterCombinationsOptimized(digits1)result2Opt := letterCombinationsOptimized(digits2)fmt.Printf("優化版本示例1: %v\n", result1Opt)fmt.Printf("優化版本示例2: %v\n", result2Opt)fmt.Printf("結果一致: %t\n", len(result1Opt) == len(result1) && len(result2Opt) == len(result2))fmt.Println()// 測試BFS版本fmt.Println("=== BFS版本測試 ===")result1BFS := letterCombinationsBFS(digits1)result2BFS := letterCombinationsBFS(digits2)fmt.Printf("BFS版本示例1: %v\n", result1BFS)fmt.Printf("BFS版本示例2: %v\n", result2BFS)fmt.Printf("結果一致: %t\n", len(result1BFS) == len(result1) && len(result2BFS) == len(result2))fmt.Println()// 測試遞歸版本fmt.Println("=== 遞歸版本測試 ===")result1Rec := letterCombinationsRecursive(digits1)result2Rec := letterCombinationsRecursive(digits2)fmt.Printf("遞歸版本示例1: %v\n", result1Rec)fmt.Printf("遞歸版本示例2: %v\n", result2Rec)fmt.Printf("結果一致: %t\n", len(result1Rec) == len(result1) && len(result2Rec) == len(result2))fmt.Println()// 邊界值測試fmt.Println("=== 邊界值測試 ===")boundaryTests := []string{"",     // 空字符串"2",    // 單個數字"99",   // 兩個相同數字"2345", // 四個不同數字"7777", // 四個相同數字}for _, test := range boundaryTests {result := letterCombinations(test)expectedCount := 1for _, digit := range test {switch digit {case '7', '9':expectedCount *= 4default:expectedCount *= 3}}fmt.Printf("digits = \"%s\", result count = %d, expected = %d\n", test, len(result), expectedCount)}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/96400.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/96400.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/96400.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

全文 part1 - DGEMM Using Tensor Cores, and Its Accurate and Reproducible Versions

摘要 本文提出了一種在 NVIDIA 圖形處理器&#xff08;GPU&#xff09;的張量核心&#xff08;Tensor Cores&#xff0c;僅含 FP16、INT8 等 GEMM 計算功能&#xff09;上實現 FP64&#xff08;雙精度&#xff0c;DGEMM&#xff09;和 FP32&#xff08;單精度&#xff0c;SGEMM…

Hexo 博客圖片托管:告別本地存儲,用 PicGo + GitHub 打造高速穩定圖床

之前剛開始進行Hexo博客撰寫&#xff0c;圖片都保存在本地Hexo源文件目錄&#xff08;source/images/&#xff09;文件夾&#xff0c;隨著圖片增多&#xff0c;管理起來壓力增大&#xff0c;于是產生了使用圖床&#xff0c;引入外鏈進行圖片存儲的想法 Pros and Cons 提升部署…

關于 VScode 無法連接 Linux 主機并報錯 <未能下載 VScode 服務器> 的解決方案

1. 出現的情況 VScode 遠程登錄 Linux 主機, 出現一下報錯:2. 檢查方案 2.1 VScode 方面 菜單欄: 點擊 <幫助> →\to→ 點擊 <關于> 在出現的彈窗中記錄 [提交: ] 之后的字符串 (暫且將該字符串命名為變量 $commit_id) 2.2 Linux 方面 使用 ssh or MobaXterm 遠程登…

泛型與反射

也是重新溫習了下泛型與反射,反射基本就是一些api理解即可,不過需要注意類加載器原理,而泛型則需要理解其設計思想,可以代替Object,更加靈活,可讀性強。泛型泛型如果指定后,編譯階段就會檢查,不讓亂輸其他類型,必須是引用類型; 如果不指定就默認Object// 如果指定泛型, 就必須存…

Docker端口映射與數據卷完全指南

目錄 Docker端口映射與數據卷完全指南 1. 端口映射:連接Docker容器與外部世界 1.1 為什么需要端口映射 1.2 實現端口映射 1.3 查看端口映射 1.4 修改端口映射(高級操作) 2. 數據卷:Docker數據持久化解決方案 2.1 數據持久化問題 2.2 數據卷的含義 2.3 數據卷的特點 2.4 掛載…

【Linux篇章】穿越網絡迷霧:揭開 HTTP 應用層協議的終極奧秘!從請求響應到實戰編程,從靜態網頁到動態交互,一文帶你全面吃透并征服 HTTP 協議,打造屬于你的 Web 通信利刃!

本篇摘要 本篇將介紹何為HTTP協議&#xff0c;以及它的請求與答復信息的格式&#xff08;請求行&#xff0c;請求包頭&#xff0c;正文等&#xff09;&#xff0c;對一些比較重要的部分來展開講解&#xff0c;其他不常用的即一概而過&#xff0c;從靜態網頁到動態網頁的過渡&a…

QT的項目pro qmake編譯

使用qmake管理Qt庫的子工程示例-CSDN博客 top_srcdir top_builddir

語音交互系統意圖識別介紹和構建

一、意圖識別簡介**意圖識別&#xff08;Intent Recognition&#xff09;**是語音交互系統的核心組件&#xff0c;用于理解用戶語音輸入背后的真實目的&#xff08;如查詢天氣、播放音樂等&#xff09;。輸入&#xff1a;語音轉文本&#xff08;ASR輸出&#xff09;的語句輸出&…

DINOv3 重磅發布

2025年8月14日 Meta 發布了 DINOv3 。 主頁&#xff1a;https://ai.meta.com/dinov3/ 論文&#xff1a;DINOv3 HuggingFace地址&#xff1a;https://huggingface.co/collections/facebook/dinov3-68924841bd6b561778e31009 官方博客&#xff1a;https://ai.meta.com/blog/d…

ansible playbook 實戰案例roles | 實現基于firewalld添加端口

文章目錄一、核心功能描述二、roles內容2.1 文件結構2.2 主配置文件2.3 tasks文件內容免費個人運維知識庫&#xff0c;歡迎您的訂閱&#xff1a;literator_ray.flowus.cn 一、核心功能描述 這個 Ansible Role (firewalld) 的核心功能是&#xff1a;動態地、安全地配置 firewal…

【深度學習實戰(55)】記錄一次在新服務器上使用docker的流程

使用docker&#xff1a;apt-get install dockersudo usermod -aG docker sliu &#xff08;將用戶 sliu 添加到 docker 用戶組&#xff09;newgrp docker &#xff08;刷新&#xff09;docker imagessudo docker load --input /home/sliu/workspace/env/shuai_docker.tar &…

面試后的跟進策略:如何提高錄用幾率并留下專業印象

面試結束后&#xff0c;許多求職者認為自己的任務已經完成&#xff0c;只需等待結果通知。然而&#xff0c;面試后的跟進策略同樣是求職過程中的關鍵環節&#xff0c;它不僅能提高你的錄用幾率&#xff0c;還能展示你的專業素養和持續興趣。本文將結合酷酷面試平臺的專業建議&a…

深入解析RAGFlow六階段架構

下面用“流程圖 六階段拆解”的方式&#xff0c;把 RAGFlow 的完整流程逐層剖開&#xff0c;力求把每一步的輸入、輸出、可選策略、內部機制都講清楚。 ──────────────────────── 一、總覽圖&#xff08;先建立體感&#xff09; 用戶提問 │ ├─→【…

Go語言中的迭代器模式與安全訪問實踐

Go語言中的迭代器模式與安全訪問實踐 1. 迭代器模式在Go中的演進 1.1 傳統迭代器模式回顧 在傳統面向對象語言中&#xff0c;迭代器模式通常涉及三個核心組件&#xff1a;可迭代集合接口(Iterable)迭代器接口(Iterator)具體實現類// 傳統迭代器模式示例 type Iterator interfac…

從零開始:JDK 在 Windows、macOS 和 Linux 上的下載、安裝與環境變量配置

前言 在進入 Java 世界之前&#xff0c;搭建一個穩定、可用的開發環境是每個開發者必須邁過的第一道門檻。JDK&#xff08;Java Development Kit&#xff09;作為 Java 程序開發的核心工具包&#xff0c;其正確安裝與環境變量配置直接關系到后續編譯、運行、調試等所有開發流程…

【音視頻】芯片、方案、市場信息收集

系統級芯片安霸&#xff08;Ambarella&#xff09;Ambarella H22/H32&#xff1a;高端方案&#xff0c;支持8K/4K高幀率錄制&#xff0c;低功耗&#xff0c;廣泛用于GoPro Hero 11/12、Insta360等旗艦機型。 Ambarella A12/A10&#xff1a;早期主流方案&#xff0c;支持4K60fps…

中科米堆CASAIM提供機加工件來料自動化測量尺寸方案

機加工行業面臨日益嚴格的質量追溯要求&#xff0c;來料質量的穩定性直接影響著后續生產效率與成品合格率。傳統人工檢測方式受限于接觸式工具的測量精度與操作效率&#xff0c;難以應對小批量、多品種的現代生產需求。傳統機加工件來料檢測長期面臨這些問題&#xff1a;其一&a…

MySQL只操作同一條記錄也會死鎖嗎?

大家好&#xff0c;我是鋒哥。今天分享關于【MySQL只操作同一條記錄也會死鎖嗎?】面試題。希望對大家有幫助&#xff1b; MySQL只操作同一條記錄也會死鎖嗎? 超硬核AI學習資料&#xff0c;現在永久免費了&#xff01; 在 MySQL 中&#xff0c;死鎖通常是由于多個事務對不同…

知識蒸餾 Knowledge Distillation 論文 Generalized Knowledge Distillation (GKD) 乘法法則、全概率公式、貝葉斯定理

知識蒸餾 Knowledge Distillation 論文 Generalized Knowledge Distillation (GKD) 乘法法則、全概率公式、貝葉斯定理 flyfish 代碼實踐 On-Policy Distillation of Language Models: Learning from Self-Generated Mistakes 設定&#xff08;方便算數&#xff09;&#x…

Fastjson 2.x踩坑——序列化Java字段為null值默認輸出

先上無法實現效果的代碼&#xff0c;我的目的是序列化時如果數字型字段為null則填0&#xff0c;盡可能保證數據整齊。 Data NoArgsConstructor AllArgsConstructor ToString JSONType(serializeFeatures {JSONWriter.Feature.WriteNulls,JSONWriter.Feature.WriteMapNullValue…