leecode 解题总结:68. Text Justification

本文介绍了一个文本格式化算法,该算法能够将给定的一系列单词按照指定的最大宽度进行格式化,确保每行文本达到完全左对齐和右对齐的效果。文章详细解释了算法的工作原理,包括如何计算每行单词的数量、如何分配空格以及如何处理最后一行的特殊格式。
#include <iostream>
#include <stdio.h>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
/*
问题:
Given an array of words and a length L, format the text such that each line has exactly L characters and is fully (left and right) justified.

You should pack your words in a greedy approach; that is, pack as many words as you can in each line. Pad extra spaces ' ' when necessary so that each line has exactly L characters.

Extra spaces between words should be distributed as evenly as possible. If the number of spaces on a line do not divide evenly between words, the empty slots on the left will be assigned more spaces than the slots on the right.

For the last line of text, it should be left justified and no extra space is inserted between words.

For example,
words: ["This", "is", "an", "example", "of", "text", "justification."]
L: 16.

Return the formatted lines as:
[
   "This    is    an",
   "example  of text",
   "justification.  "
]
Note: Each word is guaranteed not to exceed L in length.

分析:justified:合理的,pad:填塞
这是一个格式化输出的问题。本质上给定一个字符串数组和一个长度L,
1】需要摆放后每一行的长度都是L,如果不足L,需要填充空字符。
2】需要在一行中尽可能多的填充单词。
3】填充的空格需要尽可能左右两边相等,如果填充的空格部分不等,左边
   的空格可以比右边的多一些。
4】最后一行需要全部放置在左边,并且不能有额外的空格在单词之间。
这是否意味着最后一行只能放一个单词?然后不足的部分全部在右侧填充空格
理解错了,最后一行左对齐,并且单词之间不需要空格。说明是可以存放多个
单词的。

本质要使行数最少吧应该。
是否是贪心?每一行尽可能存放多个单词,这样留给剩余行摆放的单词越少,
剩余使用的行越少。
贪心问题。每一行摆放的时候,如果当前不是最后一行,那么每次摆放一个单词,需要
计算待摆放单词+至少一个空格得到的长度看是否<=L,如果符合,继续尝试下一个;
否则,说明当前行已经不能摆放了,重新开辟下一行。
如果发现待摆放单词是最后一个单词,且能在当前行摆放,则说明当前行是最后一行,
则直接讲改行所有单词拼接,最后拼接空格。

输入:
7(单词个数) 16(最大宽度)
This is an example of text justification.
输出:
This    is    an
example  of text
justification.  

关键:
1 如果只有一个空字符串,长度为0,应该直接返回空字符串数组
2 最后一行左对齐,也需要空格
Input:
["What","must","be","shall","be."]
12
Output:
["What must be","shallbe.    "]
Expected:
["What must be","shall be.   "]
3一种简单做法,每一行添加一个单词,剩余空格数减1
另外空格可以由:string(n , ' ')来生成
*/

class Solution {
public:
	string getSpaceStr(int spaceNum)
	{
		if(spaceNum <= 0)
		{
			return "";
		}
		stringstream stream;
		for(int i = 0 ; i < spaceNum; i++)
		{
			stream << ' ';
		}
		return stream.str();
	}

	string getLine(vector<string> words)
	{
		if(words.empty())
		{
			return "";
		}
		int size = words.size();
		stringstream stream;
		for(int i = 0 ; i < size ; i++)
		{
			stream << words.at(i);
		}
		return stream.str();
	}

	string getLineWithSpace(vector<string> words)
	{
		if(words.empty())
		{
			return "";
		}
		int size = words.size();
		stringstream stream;
		for(int i = 0 ; i < size ; i++)
		{
			if(i != size - 1)
			{
				stream << words.at(i) << ' ';
			}
			else
			{
				stream << words.at(i);
			}
		}
		return stream.str();
	}

	//根据每一行分组后的结果,生成最终结果
	vector<string> generate(vector<string>& words, int maxWidth , vector< vector<string> >& lines)
	{
		vector<string> result;
		if(lines.empty())
		{
			return result;
		}
		//组装结果,对除最后一行外的计算空格
		int lineSize = lines.size();
		int wordNum = 0;
		int spaceGroup = 0;
		int avgSpaceNum = 0;
		int countLen = 0;
		int spaceLen = 0;
		int remainSpaceNum = 0;
		int realSpaceNum = 0;
		string strSpace;
		int k = 0;
		string lineResult;
		for(int i = 0 ; i < lineSize - 1 ; i++ )
		{
			wordNum = lines.at(i).size();
			spaceGroup = wordNum - 1;//空格组数为单词个数-1
			countLen = 0;
			//统计单词长度
			for(int j = 0 ; j < wordNum ; j++ )
			{
				countLen += lines.at(i).at(j).length();
			}
			spaceLen = maxWidth - countLen;
			//只有一个单词
			if(spaceGroup == 0)
			{
				strSpace = getSpaceStr(spaceLen);
				lineResult = lines.at(i).at(0) + strSpace;
				result.push_back(lineResult);
				continue;
			}
			avgSpaceNum = spaceLen / spaceGroup;//可能有0组,说明只有一个单词
			remainSpaceNum = maxWidth - spaceGroup * avgSpaceNum - countLen;//别忘记减去单词本身长度
			//修改单词
			k = 0;
			while(remainSpaceNum > 0)
			{
				realSpaceNum = avgSpaceNum + 1;
				remainSpaceNum--;
				strSpace = getSpaceStr(realSpaceNum);
				if(k >= wordNum)
				{
					break;
				}
				//附加在单词之后
				lines.at(i).at(k++) += strSpace;
			}
			//最后一个单词没有空格
			while(k < wordNum - 1)
			{
				strSpace = getSpaceStr(avgSpaceNum);
				lines.at(i).at(k++) += strSpace;
			}
			lineResult = getLine(lines.at(i));
			result.push_back(lineResult);
		}
		//对最后一行,直接合并,字后一行两个单词间需要空格

		lineResult = getLineWithSpace(lines.at(lines.size() - 1));
		//看最后一行是否需要添加空格
		int tempLen = lineResult.length();
		if(tempLen < maxWidth)
		{
			strSpace = getSpaceStr(maxWidth - tempLen);
			lineResult += strSpace;
		}
		result.push_back(lineResult);
		return result;
	}

    vector<string> fullJustify(vector<string>& words, int maxWidth) 
	{
		vector<string> result;
        if(words.empty() )
		{
			return result;
		}
		if(maxWidth <= 0)
		{
			result.push_back("");
			return result;
		}
		//接下来就是摆放
		int size = words.size();
		int curLen = 0;
		int i = 0;
		int insertLen = 0;
		int lineNum = 0;
		vector< vector<string> > lines;//每一行存放该行可以摆放的位置
		while(i < size)
		{
			//计算当前单词长度
			while(i < size && curLen <= maxWidth)
			{
				insertLen = words.at(i).length() + 1;//注意最后一个单词可以不加空格
				//如果当前行能摆放,则就将当前单词插入到该行对应的结果集中
				//第一个待插入单词,长度为其本身;非第一个单词,需要多加一个空格的长度
				if(0 == curLen)
				{
					insertLen--;
				}
				if(insertLen + curLen <= maxWidth)
				{
					if(lines.empty())
					{
						vector<string> line;
						line.push_back(words.at(i));
						lines.push_back(line);
					}
					else
					{
						lines.at( lines.size() - 1 ).push_back( words.at(i) );
					}
				}
				//如果当前行不能摆放,就将最后的单词放到下一行中,这里需要直接退出,
				else
				{
					vector<string> line;
					line.push_back(words.at(i));
					lines.push_back(line);
					curLen = insertLen - 1;//重新设定新插入的长度
					i++;
					break;
				}
				curLen += insertLen;
				i++;
			}
		}
		result = generate(words , maxWidth , lines);
		return result;
    }
};

void print(vector<string>& result)
{
	if(result.empty())
	{
		cout << "no result" << endl;
		return;
	}
	int size = result.size();
	for(int i = 0 ; i < size ; i++)
	{
		cout << result.at(i) << endl ;
	}
}

void process()
{
	 vector<string> nums;
	 string value;
	 int num;
	 int maxWidth;
	 Solution solution;
	 vector<string> result;
	 while(cin >> num >> maxWidth)
	 {
		 nums.clear();
		 for(int i = 0 ; i < num ; i++)
		 {
			 cin >> value;
			 nums.push_back(value);
		 }
		 result = solution.fullJustify(nums , maxWidth);
		 print(result);
	 }
}

int main(int argc , char* argv[])
{
	process();
	getchar();
	return 0;
}


明白了,您希望在 **`orchaRd::orchard_plot`** 中仅标注出 `df$p_adjusted_T3 < 0.05` 的点,而不是改变它们的颜色或透明度。 我们可以使用 `ggplot2::geom_point()` 在已有的 orchard plot 上 **叠加一层仅包含显著点的标记**,这样这些点会在原图基础上被“强调”出来。 --- ### ✅ 解决方案代码如下: ```r # 先运行模型 lim_MR <- metafor::rma.mv( yi = df$HR_T3, V = df$Vse_T3, mods = ~ ICD.10.Chapter - 1, random = list(~1 | disease), data = df ) # 提取用于绘图的数据 mod_data <- orchaRd::mod_results(lim_MR, mod = "ICD.10.Chapter", group = "disease")$data # 添加显著性标记列 mod_data$significant <- ifelse(df$p_adjusted_T3 < 0.05, "Significant", "Non-significant") # 创建基础 orchard plot p <- orchaRd::orchard_plot( lim_MR, mod = "ICD.10.Chapter", group = "disease", xlab = "Hazard Ratio", alpha = 0.75, k = TRUE, trunk.size = 0.78, branch.size = 1.0, twig.size = 0.0001, angle = 45, fill = TRUE, cb = TRUE, refline.pos = 1 ) + theme( legend.position = c(0.02, 0.8), legend.justification = c(0, 1), legend.key.size = unit(1, "mm") ) + theme( legend.direction = "vertical", legend.title = element_text(size = 8), legend.text = element_text(size = 10) ) + labs(x = "ICD-10 chapter") # 叠加显著点(仅显示 df$p_adjusted_T3 < 0.05 的点) p <- p + geom_point( data = subset(mod_data, significant == "Significant"), aes(x = estimate, y = moderator), shape = 8, # 星号形状 size = 3, color = "red" ) # 显示图形 print(p) ``` --- ### ✅ 效果说明 - 原始所有点由 `orchard_plot` 默认绘制(颜色、透明度等保持不变) - 所有 `p_adjusted_T3 < 0.05` 的点会**额外绘制一层红色星号(`shape = 8`)** - 无需修改原有颜色或透明度,仅做**标注** --- ### ✅ 参数说明 | 参数 | 说明 | |------|------| | `shape = 8` | 使用星号形状来强调显著点 | | `color = "red"` | 红色突出显示 | | `size = 3` | 设置点的大小,使其明显可见 | | `subset(...)` | 仅选择显著点进行绘制 | --- ### ✅ 可选扩展 - 如果您希望用其他方式标注,例如加粗边框、放大点的大小等,也可以使用如下方式: ```r p <- p + geom_point( data = subset(mod_data, significant == "Significant"), aes(x = estimate, y = moderator), shape = 21, # 带边框的圆形 size = 4, fill = NA, color = "red", stroke = 1.5 # 边框加粗 ) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值