2022.02.17括号生成

本文介绍了如何使用递归深度优先搜索生成所有有效括号组合的方法。提供了两种思路:一种是生成所有组合再验证,另一种是在生成过程中确保合法性。

2022.02.17括号生成

(题目来源:https://leetcode-cn.com/problems/generate-parentheses/ )

题目描述

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

样例输入

n = 3

样例输出

["((()))","(()())","(())()","()(())","()()()"]

数据规模和约定

1 <= n <= 8

思路

思路一:

通过dfs生成所有可能的括号字符串,最后在通过一个函数判断括号是否符合。
代码如下:

	List<String> res = new ArrayList<String>();
	
	boolean fit(String s) {
		Stack<Character> stack = new Stack<>();
		int i = 0;
		while(i < s.length()) {
			if(s.charAt(i) == '(') stack.push(s.charAt(i++));
			else {
				if(stack.isEmpty() || stack.pop() != '(') return false;
				i++;
			}
		}
		return stack.isEmpty();
	}
	
	void dfs(int ln, int rn, StringBuffer sb) {
		if(ln < 0 || rn < 0) return;
		if(ln == 0 && rn == 0) {
			System.out.println(sb);
			if(fit(sb.toString())) res.add(sb.toString());
			return;
		}
		dfs(ln-1, rn, new StringBuffer(sb).append("("));
		dfs(ln, rn-1, new StringBuffer(sb).append(")"));
	}
	
	public List<String> generateParenthesis(int n) {
		dfs(n-1, n, new StringBuffer("("));
		return res;
    }

思路二

由于只有一种括号,所以只需要满足一下条件就是符合条件的字符串:
对于每个位置,其前面左括号都大于等于右括号。并且最终左括号的个数和右括号的个数相等,为n。

import pandas as pd import numpy as np from sklearn.preprocessing import MinMaxScaler import matplotlib.pyplot as plt import seaborn as sns import plotly.express as px import plotly.graph_objects as go from plotly.subplots import make_subplots import dash from dash import dcc, html, Input, Output, State import dash_bootstrap_components as dbc import os from datetime import datetime # 1. 数据预处理类 class 二课数据预处理: def __init__(self, 文件列表): self.文件列表 = 文件列表 self.合并数据 = None self.日志 = [] # 用于记录处理日志 def 记录日志(self, 消息): """记录处理日志""" 时间戳 = datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.日志.append(f"[{时间戳}] {消息}") print(f"[{时间戳}] {消息}") def 数据清洗(self): """清洗并合并所有Excel文件数据""" self.记录日志("开始数据清洗流程") dfs = [] for 文件 in self.文件列表: try: # 检查文件是否存在 if not os.path.exists(文件): self.记录日志(f"文件不存在: {文件}") continue # 检查文件扩展名 if not 文件.lower().endswith(('.xls', '.xlsx')): self.记录日志(f"文件格式不支持: {文件}") continue # 尝试读取Excel文件 try: excel_data = pd.ExcelFile(文件) if '学分明细' not in excel_data.sheet_names: self.记录日志(f"文件 {文件} 中未找到'学分明细'工作表") continue df = pd.read_excel(文件, sheet_name='学分明细') # 检查数据是否为空 if df.empty: self.记录日志(f"文件 {文件} 的'学分明细'工作表为空") continue except Exception as e: self.记录日志(f"读取文件 {文件} 时出错: {str(e)}") continue # 从文件名提取年级 年级 = 0 try: 年级_match = ''.join(filter(str.isdigit, os.path.basename(文件).split('明细')[-1])) if 年级_match: 年级 = int(年级_match) except: self.记录日志(f"无法从文件名 {文件} 提取年级信息,默认设为0") df['年级'] = 年级 dfs.append(df) self.记录日志(f"成功处理文件: {文件} (记录数: {len(df)})") except Exception as e: self.记录日志(f"处理文件 {文件} 时发生意外错误: {str(e)}") continue if not dfs: self.记录日志("错误: 没有有效数据可处理") raise ValueError("没有有效数据可处理 - 请检查: 1) 文件是否存在 2) 文件格式是否正确 3) 是否包含'学分明细'工作表") # 合并数据 self.合并数据 = pd.concat(dfs, ignore_index=True) self.记录日志(f"成功合并数据,总记录数: {len(self.合并数据)}") # 数据清洗 columns_to_drop = ['单位', '活动分类', '数量', '获取原因', '发送人', '参与时长(分)', '参与开始时间', '参与结束时间', '获取时间'] # 检查是否有要删除的列 existing_columns = [col for col in columns_to_drop if col in self.合并数据.columns] self.合并数据 = self.合并数据[self.合并数据['是否有效'] == '是'].drop(columns=existing_columns, errors='ignore') self.记录日志(f"数据清洗完成,剩余记录数: {len(self.合并数据)}") return self.合并数据 def 构建评价模型(self): """构建二课积分评价模型""" self.记录日志("开始构建评价模型") if self.合并数据 is None: self.数据清洗() # 检查必要列是否存在 required_columns = ['院系', '年级', '班级', '学号', '姓名', '学分类型', '转换后学分'] missing_columns = [col for col in required_columns if col not in self.合并数据.columns] if missing_columns: self.记录日志(f"错误: 缺少必要列 {missing_columns}") raise ValueError(f"数据中缺少必要列: {missing_columns}") # 按学分类型分组计算 try: pivot_df = self.合并数据.groupby(['院系', '年级', '班级', '学号', '姓名', '学分类型'])['转换后学分'].sum().unstack(fill_value=0).reset_index() except Exception as e: self.记录日志(f"分组计算失败: {str(e)}") raise # 重命名列 pivot_df.rename(columns={ '创新创业': '创新创业转换后学分', '综合素养': '综合素养转换后学分', '社会实践与劳动教育': '社会实践与劳动教育转换后学分' }, inplace=True) # 检查是否有缺失的学分类型 for col in ['创新创业转换后学分', '综合素养转换后学分', '社会实践与劳动教育转换后学分']: if col not in pivot_df.columns: pivot_df[col] = 0 self.记录日志(f"警告: 缺少学分类型 {col},已设为0") # 计算原始得分 pivot_df['二课原始得分'] = pivot_df[['创新创业转换后学分', '综合素养转换后学分', '社会实践与劳动教育转换后学分']].sum(axis=1) # 标准化处理 try: scaler = MinMaxScaler() 标准化得分 = scaler.fit_transform(pivot_df[['创新创业转换后学分', '综合素养转换后学分', '社会实践与劳动教育转换后学分']]) pivot_df[['创新创业标准化', '综合素养标准化', '社会实践标准化']] = 标准化得分 except Exception as e: self.记录日志(f"标准化处理失败: {str(e)}") raise # 计算综合得分(可调整权重) 权重 = { '创新创业标准化': 0.4, '综合素养标准化': 0.3, '社会实践标准化': 0.3 } pivot_df['二课综合得分'] = (pivot_df['创新创业标准化'] * 权重['创新创业标准化'] + pivot_df['综合素养标准化'] * 权重['综合素养标准化'] + pivot_df['社会实践标准化'] * 权重['社会实践标准化']) # 按综合得分排名 pivot_df['综合排名'] = pivot_df.groupby(['院系', '年级'])['二课综合得分'].rank(ascending=False, method='min') pivot_df['原始排名'] = pivot_df.groupby(['院系', '年级'])['二课原始得分'].rank(ascending=False, method='min') # 保存处理结果 self.处理结果 = pivot_df.round(2) self.记录日志(f"评价模型构建完成,共处理 {len(self.处理结果)} 条记录") return self.处理结果 # 2. 可视化分析类 class 二课可视化分析: def __init__(self, 处理后的数据): self.df = 处理后的数据 self.颜色映射 = { '2022': '#1f77b4', '2023': '#ff7f0e', '2024': '#2ca02c' } def 生成雷达图(self, 学生列表=None, 年级=None): if 学生列表 is None and 年级 is not None: 学生列表 = self.df[self.df['年级'] == 年级].sort_values('二课综合得分', ascending=False).head(5)['姓名'].tolist() if not 学生列表: 学生列表 = self.df.sort_values('二课综合得分', ascending=False).head(5)['姓名'].tolist() 筛选数据 = self.df[self.df['姓名'].isin(学生列表)] fig = go.Figure() for _, row in 筛选数据.iterrows(): fig.add_trace(go.Scatterpolar( r=[row['创新创业标准化'], row['综合素养标准化'], row['社会实践标准化']], theta=['创新创业', '综合素养', '社会实践'], fill='toself', name=f"{row['姓名']} (综合得分: {row['二课综合得分']:.2f})" )) fig.update_layout( polar=dict( radialaxis=dict( visible=True, range=[0, 1] )), showlegend=True, title='学生二课积分雷达图对比' ) return fig def 生成折线图(self, 院系=None, 年级=None): if 院系 and 年级: 筛选数据 = self.df[(self.df['院系'] == 院系) & (self.df['年级'] == 年级)] elif 院系: 筛选数据 = self.df[self.df['院系'] == 院系] elif 年级: 筛选数据 = self.df[self.df['年级'] == 年级] else: 筛选数据 = self.df # 按班级和学号排序 筛选数据 = 筛选数据.sort_values(['班级', '学号']) fig = go.Figure() # 添加综合得分线 fig.add_trace(go.Scatter( x=筛选数据['姓名'], y=筛选数据['二课综合得分'], mode='lines+markers', name='综合得分', line=dict(color='red', width=2) )) # 添加各维度得分柱状图 fig.add_trace(go.Bar( x=筛选数据['姓名'], y=筛选数据['创新创业转换后学分'], name='创新创业', marker_color='#3498db' )) fig.add_trace(go.Bar( x=筛选数据['姓名'], y=筛选数据['综合素养转换后学分'], name='综合素养', marker_color='#2ecc71' )) fig.add_trace(go.Bar( x=筛选数据['姓名'], y=筛选数据['社会实践与劳动教育转换后学分'], name='社会实践', marker_color='#f39c12' )) fig.update_layout( barmode='group', title='学生二课积分分布', xaxis_title='学生姓名', yaxis_title='积分', xaxis_tickangle=-45 ) return fig def 生成热力图(self): # 计算相关系数 corr_matrix = self.df[['创新创业转换后学分', '综合素养转换后学分', '社会实践与劳动教育转换后学分']].corr() fig = go.Figure(data=go.Heatmap( z=corr_matrix.values, x=corr_matrix.columns, y=corr_matrix.columns, colorscale='Viridis', zmin=-1, zmax=1, hoverongaps=False, colorbar=dict(title='相关系数') ) fig.update_layout( title='二课积分维度相关性分析' ) return fig def 生成年级对比图(self): 年级数据 = self.df.groupby('年级').agg({ '创新创业转换后学分': 'mean', '综合素养转换后学分': 'mean', '社会实践与劳动教育转换后学分': 'mean' }).reset_index() fig = make_subplots(rows=1, cols=2, specs=[[{'type': 'bar'}, {'type': 'pie'}]]) # 柱状图 for col in ['创新创业转换后学分', '综合素养转换后学分', '社会实践与劳动教育转换后学分']: fig.add_trace( go.Bar( x=年级数据['年级'].astype(str), y=年级数据[col], name=col.split('转换后')[0] ), row=1, col=1 ) # 饼图 fig.add_trace( go.Pie( labels=['创新创业', '综合素养', '社会实践'], values=年级数据.mean()[['创新创业转换后学分', '综合素养转换后学分', '社会实践与劳动教育转换后学分']], hole=0.3 ), row=1, col=2 ) fig.update_layout( title_text='各年级二课积分对比', showlegend=True ) return fig # 3. 交互式大屏应用 def 创建交互式大屏(处理后的数据): # 初始化可视化分析类 可视化分析 = 二课可视化分析(处理后的数据) # 初始化Dash应用 app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP]) # 获取筛选选项 院系列表 = sorted(处理后的数据['院系'].unique().tolist()) 年级列表 = sorted(处理后的数据['年级'].unique().tolist()) 班级列表 = sorted(处理后的数据['班级'].unique().tolist()) app.layout = dbc.Container([ dbc.Row([ dbc.Col(html.H1("学生二课积分分析大屏", className="text-center mb-4"), width=12) ]), dbc.Row([ dbc.Col([ dbc.Card([ dbc.CardHeader("筛选条件"), dbc.CardBody([ dbc.Row([ dbc.Col([ dcc.Dropdown( id='院系筛选', options=[{'label': x, 'value': x} for x in 院系列表], placeholder="选择院系" ) ], width=6), dbc.Col([ dcc.Dropdown( id='年级筛选', options=[{'label': str(x), 'value': x} for x in 年级列表], placeholder="选择年级" ) ], width=6) ]), dbc.Row([ dbc.Col([ dcc.Dropdown( id='班级筛选', options=[{'label': x, 'value': x} for x in 班级列表], placeholder="选择班级", multi=True ) ], width=12) ], className="mt-2"), dbc.Row([ dbc.Col([ dcc.Dropdown( id='学生筛选', placeholder="选择学生(可多选)", multi=True ) ], width=12) ], className="mt-2"), dbc.Row([ dbc.Col([ dbc.Button("应用筛选", id="筛选按钮", color="primary", className="w-100") ], width=12) ], className="mt-2"), dbc.Row([ dbc.Col([ html.Div(id='状态提示', className="text-muted small") ], width=12) ], className="mt-2") ]) ]) ], width=3), dbc.Col([ dbc.Card([ dbc.CardHeader("二课积分统计概览"), dbc.CardBody([ dbc.Row([ dbc.Col([ dbc.Card([ dbc.CardHeader("平均综合得分"), dbc.CardBody([ html.H4(id='平均综合得分', className="card-title text-center") ]) ], className="h-100") ], width=4), dbc.Col([ dbc.Card([ dbc.CardHeader("最高综合得分"), dbc.CardBody([ html.H4(id='最高综合得分', className="card-title text-center") ]) ], className="h-100") ], width=4), dbc.Col([ dbc.Card([ dbc.CardHeader("参与学生数"), dbc.CardBody([ html.H4(id='学生总数', className="card-title text-center") ]) ], className="h-100") ], width=4) ]), dbc.Row([ dbc.Col([ dcc.Graph(id='年级对比图') ], width=12) ], className="mt-3") ]) ], className="h-100") ], width=9) ], className="mb-4"), dbc.Row([ dbc.Col([ dbc.Card([ dbc.CardHeader("学生积分雷达图"), dbc.CardBody([ dcc.Graph(id='雷达图') ]) ]) ], width=6), dbc.Col([ dbc.Card([ dbc.CardHeader("维度相关性分析"), dbc.CardBody([ dcc.Graph(id='热力图') ]) ]) ], width=6) ], className="mb-4"), dbc.Row([ dbc.Col([ dbc.Card([ dbc.CardHeader("学生积分详细分布"), dbc.CardBody([ dcc.Graph(id='折线图') ]) ]) ], width=12) ]), dbc.Row([ dbc.Col([ dbc.Card([ dbc.CardHeader("数据明细"), dbc.CardBody([ html.Div(id='数据表') ]) ]) ], width=12) ], className="mb-4") ], fluid=True) # 回调函数 @app.callback( Output('班级筛选', 'options'), Input('院系筛选', 'value'), Input('年级筛选', 'value'), prevent_initial_call=True ) def 更新班级选项(selected_院系, selected_年级): if not selected_院系 and not selected_年级: return dash.no_update 筛选数据 = 处理后的数据.copy() if selected_院系: 筛选数据 = 筛选数据[筛选数据['院系'] == selected_院系] if selected_年级: 筛选数据 = 筛选数据[筛选数据['年级'] == selected_年级] 可选班级 = sorted(筛选数据['班级'].unique().tolist()) return [{'label': x, 'value': x} for x in 可选班级] @app.callback( Output('学生筛选', 'options'), Input('院系筛选', 'value'), Input('年级筛选', 'value'), Input('班级筛选', 'value'), prevent_initial_call=True ) def 更新学生选项(selected_院系, selected_年级, selected_班级): if not selected_院系 and not selected_年级 and not selected_班级: return dash.no_update 筛选数据 = 处理后的数据.copy() if selected_院系: 筛选数据 = 筛选数据[筛选数据['院系'] == selected_院系] if selected_年级: 筛选数据 = 筛选数据[筛选数据['年级'] == selected_年级] if selected_班级: 筛选数据 = 筛选数据[筛选数据['班级'].isin(selected_班级)] 可选学生 = sorted(筛选数据['姓名'].unique().tolist()) return [{'label': x, 'value': x} for x in 可选学生] @app.callback( [Output('雷达图', 'figure'), Output('折线图', 'figure'), Output('热力图', 'figure'), Output('年级对比图', 'figure'), Output('平均综合得分', 'children'), Output('最高综合得分', 'children'), Output('学生总数', 'children'), Output('数据表', 'children'), Output('状态提示', 'children')], Input('筛选按钮', 'n_clicks'), [State('院系筛选', 'value'), State('年级筛选', 'value'), State('班级筛选', 'value'), State('学生筛选', 'value')], prevent_initial_call=True ) def 更新所有图表(n_clicks, selected_院系, selected_年级, selected_班级, selected_学生): 筛选数据 = 处理后的数据.copy() 状态消息 = "" # 应用筛选条件 if selected_院系: 筛选数据 = 筛选数据[筛选数据['院系'] == selected_院系] 状态消息 += f"院系: {selected_院系} | " if selected_年级: 筛选数据 = 筛选数据[筛选数据['年级'] == selected_年级] 状态消息 += f"年级: {selected_年级} | " if selected_班级: 筛选数据 = 筛选数据[筛选数据['班级'].isin(selected_班级)] 状态消息 += f"班级: {', '.join(selected_班级)} | " if selected_学生: 筛选数据 = 筛选数据[筛选数据['姓名'].isin(selected_学生)] 状态消息 += f"学生: {len(selected_学生)}人" # 生成图表 try: 雷达图 = 可视化分析.生成雷达图(selected_学生, selected_年级) if selected_学生 else 可视化分析.生成雷达图(年级=selected_年级) 折线图 = 可视化分析.生成折线图(selected_院系, selected_年级) 热力图 = 可视化分析.生成热力图() 年级对比图 = 可视化分析.生成年级对比图() # 计算统计指标 平均综合得分 = f"{筛选数据['二课综合得分'].mean():.2f}" 最高综合得分 = f"{筛选数据['二课综合得分'].max():.2f}" 学生总数 = f"{len(筛选数据)}人" # 生成数据表 数据表 = dash.dash_table.DataTable( columns=[{"name": i, "id": i} for i in 筛选数据.columns], data=筛选数据.to_dict('records'), page_size=10, style_table={'overflowX': 'auto'}, style_cell={ 'textAlign': 'left', 'padding': '5px' }, style_header={ 'backgroundColor': 'rgb(230, 230, 230)', 'fontWeight': 'bold' } ) return 雷达图, 折线图, 热力图, 年级对比图, 平均综合得分, 最高综合得分, 学生总数, 数据表, 状态消息 or "未应用筛选条件" except Exception as e: print(f"生成图表时出错: {str(e)}") return go.Figure(), go.Figure(), go.Figure(), go.Figure(), "N/A", "N/A", "0", html.Div("数据加载失败"), f"错误: {str(e)}" return app # 主程序 def 主程序(): print("=== 学生二课积分分析系统 ===") # 获取当前脚本所在目录 base_dir = os.path.dirname(os.path.abspath(__file__)) if '__file__' in globals() else os.getcwd() print(f"当前工作目录: {base_dir}") # 定义文件列表 文件列表 = [ os.path.join(base_dir, '学分明细2022.xlsx'), os.path.join(base_dir, '学分明细2023级.xlsx'), os.path.join(base_dir, '学分明细2024级.xlsx') ] # 检查文件是否存在 print("\n检查数据文件:") 有效文件 = [] for 文件 in 文件列表: if os.path.exists(文件): print(f"✓ {文件}") 有效文件.append(文件) else: print(f"× {文件} (文件不存在)") if not 有效文件: print("\n错误: 没有找到任何有效数据文件!") print("请确保以下文件存在于当前目录:") for 文件 in 文件列表: print(f"- {os.path.basename(文件)}") exit(1) # 1. 数据预处理 print("\n开始数据预处理...") 数据处理器 = 二课数据预处理(有效文件) try: 处理后的数据 = 数据处理器.构建评价模型() print(f"\n数据处理完成,共 {len(处理后的数据)} 条记录") except Exception as e: print(f"\n数据处理失败: {str(e)}") print("\n处理日志:") for 日志 in 数据处理器.日志: print(日志) exit(1) # 2. 创建交互式大屏 print("\n创建交互式大屏...") app = 创建交互式大屏(处理后的数据) # 3. 运行应用 print("\n启动Dash应用...") print(f"请在浏览器中访问: http://localhost:8050") app.run_server(debug=True, port=8050) if __name__ == "__main__": 主程序() 以上代码出现File "C:\Users\w10\AppData\Local\Temp\ipykernel_49596\3947897257.py", line 278 fig.update_layout( ^ SyntaxError: invalid syntax
06-30
从错误信息来看,Python 报告了语法错误(`SyntaxError: invalid syntax`),这通常意味着代码中存在拼写错误、括号不匹配、缩进问题或使用了非法字符等。根据你提供的错误位置: ```python fig.update_layout( ``` 错误可能出现在 `fig.update_layout(...)` 附近的上下文中,但你的错误信息没有显示完整的代码段。为了更准确地定位,我将假设是与该函数调用相关的问题,并给出修正后的完整代码片段。 --- ### ✅ 修复后的示例代码(以生成雷达图方法中的 `update_layout` 为例) ```python def 生成雷达图(self, 学生列表=None, 年级=None): if 学生列表 is None and 年级 is not None: 学生列表 = self.df[self.df['年级'] == 年级].sort_values('二课综合得分', ascending=False).head(5)['姓名'].tolist() if not 学生列表: 学生列表 = self.df.sort_values('二课综合得分', ascending=False).head(5)['姓名'].tolist() 筛选数据 = self.df[self.df['姓名'].isin(学生列表)] fig = go.Figure() for _, row in 筛选数据.iterrows(): fig.add_trace(go.Scatterpolar( r=[row['创新创业标准化'], row['综合素养标准化'], row['社会实践标准化']], theta=['创新创业', '综合素养', '社会实践'], fill='toself', name=f"{row['姓名']} (综合得分: {row['二课综合得分']:.2f})" )) fig.update_layout( polar=dict( radialaxis=dict( visible=True, range=[0, 1] ) ), showlegend=True, title='学生二课积分雷达图对比' ) return fig ``` --- ### 🔍 可能的错误原因分析 | 错误类型 | 描述 | 修复建议 | |----------|------|-----------| | 缺少右括号 | `fig.update_layout(` 后缺少对应的 `)` | 检查是否在调用后正确闭合所有括号 | | 中文符号 | 使用了中文逗号、引号等 | 替换为英文半角符号 | | 缩进错误 | Python 对缩进敏感 | 统一使用空格或制表符进行缩进 | | 字典结构错误 | 如 `radialaxis=dict(...` 括号未闭合 | 检查嵌套结构是否完整闭合 | | 文件编码问题 | 使用了非 UTF-8 编码保存文件 | 保存为 UTF-8 格式 | --- ### ✅ 建议操作步骤 1. **检查报错行前后的代码**:查看是否有遗漏的括号、逗号或冒号。 2. **确认是否使用了中文标点**:例如全角逗号 `,` 应改为 `,`。 3. **检查 `go.Scatterpolar` 或其他 Plotly 调用的参数是否完整闭合**。 4. **使用 IDE 的语法高亮功能辅助排查**(如 VS Code、PyCharm)。 5. **运行 linter 工具**(如 `flake8`)来自动检测语法问题。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值